如果此表没有子表(没有引用它的外键),为了节省空间,您可以考虑省略代理主键(id)
,而是使用复合键(productId,date_)
作为主键。(根据您的描述,听起来您希望将这些列的组合设为 UNIQUE,并且将这两个列都设为 NOT NULL。
如果您要存储的是“周”标识符而不是 DATE,那么在数据库方面没有问题,只要您的查询没有将该列包装在表达式中以获取要在谓词中使用的 DATE 值. 也就是说,为了性能,您的谓词将需要位于“星期标识符”列,例如
WHERE t.product_id = 195 AND t.week_id >= 27 AND t.week_id < 40
像这样在裸列上的谓词将是 sargable(即,允许使用索引。)您不想将该week_id
列包装在表达式中以返回 DATE,并在该表达式上使用 WHERE 子句。(在比较的文字方面有表达式不是问题......你只是不希望它们在“表”方面。
这确实将成为您是否可以使用 aweek_id
代替 DATE 列的决定因素。
使用“期间 id”代替 DATE 对于整月的期间实施起来相当简单。(“天”也很简单,但在那里实际上没有什么好处。)在“周”期间实施这种方法更加复杂,因为您需要在两年之间进行一周的处理。
例如,考虑一下,今年(2012 年)的最后两天是周日和周一,但同一周的周二到周六是 2013 年。你需要决定这是两个单独的星期,还是那是同一周。
但是(SMALLINT 与 DATE 的)节省 1 字节并不是真正的好处。“week_id”列让你(如我所见)是你有一个标识一周的 id 值。考虑,的日期值'2012-07-30'
,它们实际上都代表同一周。所以你有多个一周的值,这样一个 UNIQUE 约束并不能真正保证(在数据库方面)你在同一周没有超过行。(这当然不是一个无法克服的问题,您可以指定只存储一个星期日(或星期一)的日期值。)'2012-07-31'
'2012-08-01'
(product_id,date)
总之,
为了节省空间,我将首先删除该代理id
列,并将 product_id 和 DATE 的组合作为主键。
然后我只会考虑将该 DATE 更改为 SMALLINT,如果我可以保证所有查询都将引用该裸 SMALLINT 列,而不是引用将 SMALLINT 列转换回 DATE 的表达式。