6

我的表“my_logs”有大约 20,000,000 条记录,我想在几天内找出每个日期有多少日志。

我想要这样的结果

+------------+---------+ | date | count | +------------+---------+ | 2016-07-01 | 1623 | | 2016-07-02 | 1280 | | 2016-07-03 | 2032 | +------------+---------+

下面的这个查询只需要我几毫秒就可以完成,很好

SELECT  DATE_FORMAT(created_at, '%Y-%m-%d') as date,
        COUNT(*) as count
    FROM  my_logs
    WHERE  created_at BETWEEN '2016-07-01' AND '2016-07-04'
    GROUP BY  DATE_FORMAT(created_at, '%Y-%m-%d')

查询说明:

+------------+---------+-------+-----------------------------+ |select_type | table | type | possible_keys | +------------+---------+-------+-----------------------------+ | SIMPLE | my_logs| index | index_my_logs_on_created_at | +------------+---------+-------+-----------------------------+

+-----------------------------+---------+----------+ | key | key_len | rows | +-----------------------------+---------+----------+ | index_my_logs_on_created_at | 10 | 23458462 | +-----------------------------+---------+----------+

+-----------------------------------------------------------+ | Extra | +-----------------------------------------------------------+ | Using where; Using index; Using temporary; Using filesort | +-----------------------------------------------------------+

但是,我需要转换每条记录的时区以适应我所在国家/地区的时间,并且我需要按“日期”信息进行分组,因此我需要转换列本身。

两个都

SELECT  COUNT(*)
    FROM  my_logs
    WHERE  DATE_ADD(created_at, INTERVAL 8 HOUR) BETWEEN '2016-07-01' AND '2016-07-04'
    GROUP BY  DATE_FORMAT(DATE_ADD(created_at, INTERVAL 8 HOUR), '%Y-%m-%d')

SELECT  COUNT(*)
    FROM  my_logs
    WHERE  CONVERT_TZ(created_at, "+00:00", "+08:00") BETWEEN '2016-07-01' AND '2016-07-04'
    GROUP BY  DATE_FORMAT(CONVERT_TZ(created_at, "+00:00", "+08:00"),

'%Y-%m-%d')

大概12秒完成查询,慢得受不了!!

(解释与顶部的查询相同)


我认为这是常见问题,但我找不到处理它的好方法,有人有更有效的方法吗?谢谢!

4

1 回答 1

4

您使用了哪种数据TIMESTAMP类型DATETIME?(但是,我会忽略这一点。)

不要created_at在任何函数 ( ) 中“隐藏”索引列 ( CONVERT_TZ())。它使WHERE子句不能使用索引,而必须扫描表。这个修复很简单:

WHERE created_at >= '2016-07-01' - INTERVAL 8 HOUR
  AND created_at  < '2016-07-04' - INTERVAL 8 HOUR

(或使用CONVERT_TZ)。请注意,我还修复了您从 4 日开始包含午夜的错误。注意: Even+ INTERVAL...实际上是一个函数。

SELECTthe和 the中的表达式GROUP BY对性能的影响要小得多。

于 2016-08-25T20:41:45.613 回答