【问题标题】:SQL Performance of grouping by DATE(TIMESTAMP) vs separate columns for DATE and TIME按 DATE(TIMESTAMP) 分组的 SQL 性能与 DATE 和 TIME 的单独列
【发布时间】:2014-08-14 18:50:34
【问题描述】:

我遇到了从 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 个查询:INSERT(针对每个请求)和 SELECT 来创建此数据。

标签: mysql sql performance


【解决方案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

【讨论】:

  • 是的,我确实有时间索引。当然,我会将结果限制在最后 7 天,但由于负载很大,它可能有很多行要处理。
  • 好吧,在文件排序中,有七行,每天一行,不会花很长时间。 MySQL 仍然需要扫描索引来获得结果,但这也相当快。
【解决方案2】:

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

其他选择是:

  • 按月使用分区表。

  • 使用materialized views

  • 每次访问时更新计数器。

  • 预先计算和存储昨天的数据。只需使用 WHERE DAY(timestamp) = TODAY 刷新您的每日访问。这样,serer 将不得不对少量数据进行排序。

取决于用户访问您的页面的频率以及您何时需要这些数据。如果不需要,不要过早优化。

【讨论】:

  • 这是 MySQL。没有物化视图。
猜你喜欢
  • 2012-08-13
  • 1970-01-01
  • 2018-04-06
  • 2017-06-15
  • 1970-01-01
  • 1970-01-01
  • 2020-02-11
  • 2011-04-21
  • 2016-04-21
相关资源
最近更新 更多