我遇到了从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列创建组? 处理此类问题的其他好方法是什么?缓存?另一个数据库引擎?
答案 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索引可能会有所帮助,因为它会以每次插入时刷新另一个索引为代价来提高查询速度。请测试一下,我不是百分百肯定。
其他替代方案是:
按月使用分区表。
每次访问都会更新计数器。
预先计算并存储昨天的数据。只需在WHERE DAY(时间戳)=今天刷新您的每日访问次数。这样,服务器必须对较少量的数据进行排序。
取决于用户访问您网页的频率以及何时需要此数据。如果您不需要,请不要进行prematuraly优化。