SmallInt与MySQL中的日期 - 性能,灵活性和大小

时间:2012-07-30 15:45:00

标签: mysql sql

我正在创建一个表,用于存储每周产品的数据,实际上是计数器。

示例:

 id = 1
 productId = 195
 DateTime = 01/07/2012
 Counter = 0

我的问题是关于数据库存储空间,查询灵活性和性能。

我没有使用DateTime列,而是考虑使用SmallInt“WeekNumber”列。

我将决定周开始的日期(基准日期)。比如说10/10/2012。

对于每个产品和每周,都会有一行代表我每天都要计算的总数(即特定产品页面的网页浏览量)。

从我的内容:

日期列为4个字节

SmallInt是2个字节

我希望尽可能多地节省空间,但我希望能够根据日期范围(2012年8月至2013年9月),特定年份的特定周等查询数据库。

这种架构方法是否良好,或者我发现自己在SQL性能不佳,查询灵活性,索引等方面存在问题。

2 个答案:

答案 0 :(得分:3)

考虑为了保存 2个字节 一个字节而要做出的牺牲和复杂化......

为了使用smallint,您将通过函数传递对数据的每次调用,以从您自己的任意日期开始获取其“周数”....这既不是更高效也不是更清晰。

同样,查询不够灵活,因为每个人都需要根据您的魔术“开始日期”进行比较,而不仅仅是日期比较/组。您的查询可能不是SARGable,可能较慢

编辑:根据您的评论,您的硬限制为50GB ....这就像您正在讨论的聚合数据库一样。通过使这一点复杂化,你正在招致过度的压力和可持续性的丧失。

根据MySQL,DATE类型只有3个字节,而SMALLINT只有2个字节

http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html

因此,您将每行保存一个字节(您说每周2000个)...所以我们说每周2KB,每年104 KB ......

答案 1 :(得分:2)

如果此表没有子表(没有外键引用它),为了节省空间,您可以考虑省略代理主键(id),而是使用复合键(productId,date_)作为主表键。 (根据您的描述,听起来您希望将这些列的组合作为UNIQUE,并将这两列作为NOT NULL。

如果你要存储的是一个“周”标识符而不是DATE,那么数据库方面没有问题,只要你的查询没有在表达式中包装该列以获取DATE值在谓词中使用。也就是说,为了提高性能,您的谓词将需要在明确的“周标识符”列上,例如

WHERE t.product_id = 195 AND t.week_id >= 27 AND t.week_id < 40

裸列上的谓词将是可搜索的(即允许使用索引。)您不希望在表达式中包装week_id列以返回DATE,并使用关于该表达式的WHERE子句。 (在比较的字面上有表达式不是问题...你只是不希望它们在“表”一侧。

这确实是您是否可以使用week_id代替DATE列的决定性因素。

使用“句点ID”代替DATE对于整月的时段来说非常简单。 (它对于“天”来说也很简单,但在那里实际上效果不大。)在“周”期间实施这种方法更复杂,因为你需要处理两周之间的一周。

例如,考虑今年(2012年)的最后两天是星期日和星期一,但同一周的星期二至星期六是在2013年。你需要决定这是两个星期,或者是否是同一周。

但是,1字节的节省(SMALLINT与DATE的节省)并不是真正的好处。 “week_id”列给你的东西(我看到的)是你有一个标识一周的id值。考虑'2012-07-30''2012-07-31''2012-08-01'的日期值,它们实际上代表同一周。因此,您有一周的多个值,因此(product_id,date)上的UNIQUE约束并不真正保证(在数据库端)您在同一周内没有多行。 (当然,这不是一个不可逾越的问题,您可以指定只存储星期日(或星期一)日期值。)


总之,

为了节省空间,我首先删除该代理id列,并将product_id和DATE的组合作为主键。

然后我 ONLY 考虑将DATE更改为SMALLINT,如果我可以保证所有查询都将引用该裸SMALLINT列,并且不引用将SMALLINT列转换回DATE的表达式