优化日期组的mysql查询

时间:2016-04-04 11:21:58

标签: mysql optimization indexing

这是我的表格:

CREATE TABLE IF NOT EXISTS `test_dates` (
  `date` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `test_log` (
  `id` int(10) unsigned NOT NULL,
  `timest` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `test_dates`
  ADD PRIMARY KEY (`date`);

ALTER TABLE `test_log`
  ADD PRIMARY KEY (`id`),
  ADD KEY `emissione` (`timest`);

我有这个查询来计算每个日期的日志:

SELECT d.date, COUNT(l.id) 
FROM test_dates d
LEFT JOIN test_log l ON l.timest>=d.date AND l.timest<d.date + INTERVAL 1 DAY 
GROUP BY d.date

test_dates 在日期列中编入索引, test_log 表在timest列中编入索引。

但是解释这个查询我得到了查询类型“ALL”和NULL键。

+-----+--------------+--------+-------------+--------+----------------+----------+----------+------+--------+-----------+------------------------------------------------+--+
| id  | select_type  | table  | partitions  | type   | possible_keys  |   key    | key_len  | ref  | rows   | filtered  |                     Extra                      |  |
+-----+--------------+--------+-------------+--------+----------------+----------+----------+------+--------+-----------+------------------------------------------------+--+
|  1  | SIMPLE       | d      | NULL        | index  | PRIMARY        | PRIMARY  | 3        | NULL |   705  | 100.00    | Using index                                    |  |
|  1  | SIMPLE       | l      | NULL        | ALL    | emissione      | NULL     | NULL     | NULL | 98256  | 100.00    | Range checked for each record (index map: 0x2) |  |
+-----+--------------+--------+-------------+--------+----------------+----------+----------+------+--------+-----------+------------------------------------------------+--+

为什么mysql不能使用表索引?

日志表有大约100000行,查询速度很慢。

3 个答案:

答案 0 :(得分:2)

尝试将其作为相关子查询运行:

SELECT d.date,
       (SELECT COUNT(l.id) 
        FROM log l 
        WHERE l.timest >= d.date AND l.timest < d.date + INTERVAL 1 DAY 
       ) as cnt
FROM dates d;

使用GROUP BY的索引时,MySQL不是很好。有时使用子查询可以显着提升性能。你的表有正确的索引。

答案 1 :(得分:0)

如果索引和相关子查询不适合您,则更好的选择可能是更新日期表并添加摘要计数列。然后,当您在日志表中插入时,在日期表中将计数器中的1添加到计数器中。如果还没有这样的记录,添加一个并将其计数设置为1,因为它是一个新记录。

然后,您需要做的就是根据日期范围从日期表中选择一个sum(),而不是查看详细信息。一旦选择了给定日期进行可能的审核,您就可以查询基础数据。

答案 2 :(得分:0)

Turn it around. First do an efficient GROUP BY on the second table (see subquery, below), then fill in the missing days (outer query):

SELECT  date,
        IFNULL(log.ct, 0) AS ct
    FROM  
      ( SELECT  DATE(timest) AS date,
                COUNT(*) AS ct
            FROM  test_log 
            GROUP BY date
      ) AS log
    RIGHT JOIN  test_dates AS d  USING(date);

If you want to limit the date range, add a WHERE clause in both the subquery and the outer query.