SQL按DATE(TIMESTAMP)分组的性能​​与DATE和TIME的单独列

时间:2014-06-24 13:23:01

标签: mysql sql performance

我遇到了从MySQL数据库显示数据的问题。 我有一个包含所有用户请求的表格格式:

| TIMESTAMP Time / +INDEX | Some other params |

我想在我的网站上将这些数据显示为每天请求数量的表格。

查询非常简单:

SELECT DATE(Time) as D, COUNT(*) as S FROM Stats GROUP BY D ORDER BY D DESC

但是在查看EXPLAIN时,这让我很生气:

Using index; **Using temporary; Using filesort**

从MySQL文档中可以看出,它为硬盘驱动器上的此查询创建了临时表。

1.000.000记录的速度有多快?而100.000.000的速度有多快?

有没有办法把INDEX放在功能结果上? 也许我应该为DATE和TIME创建单独的列,而不是按DATE列创建组? 处理此类问题的其他好方法是什么?缓存?另一个数据库引擎?

2 个答案:

答案 0 :(得分:1)

如果您的Time列上有索引,此操作的效果会非常好。我猜测你确实有这个索引,因为你的EXPLAIN输出显示它使用索引。

为什么这样做效果很好?因为MySQL可以按顺序访问此索引 - 它可以扫描索引 - 以满足您的查询。

不要被Using temporary; Using filesort弄糊涂。这只是意味着MySQL需要创建并返回每天都有一行的虚拟表。这非常小,几乎肯定适合记忆。 filesort并不一定意味着文件已溢出到磁盘上的临时文件中;它只是意味着MySQL必须对虚拟表进行排序。它必须对它进行排序才能获得最后一天。

顺便说一句,如果您可以限制查询的日期范围,即使您的应用程序已使用多年,您也可以在此查询中获得可预测的性能。试试这个:

SELECT DATE(Time) as D, COUNT(*) as S 
  FROM Stats
 WHERE Time >= CURDATE() - INTERVAL 30 DAY 
  GROUP BY D ORDER BY D DESC

答案 1 :(得分:0)

首先:GROUP BY意味着排序,这是一项昂贵的操作。索引中的数据已排序,但即使在这种情况下,ddbb也需要对日期进行分组。所以我觉得DATE索引可能会有所帮助,因为它会以每次插入时刷新另一个索引为代价来提高查询速度。请测试一下,我不是百分百肯定。

其他替代方案是:

  • 按月使用分区表。

  • 使用materialized views

  • 每次访问都会更新计数器。

  • 预先计算并存储昨天的数据。只需在WHERE DAY(时间戳)=今天刷新您的每日访问次数。这样,服务器必须对较少量的数据进行排序。

取决于用户访问您网页的频率以及何时需要此数据。如果您不需要,请不要进行prematuraly优化。