这是我的表格:
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行,查询速度很慢。
答案 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.