如何优化以下查询?我试图创建索引(idx_events,idx_events_startdate,但它们没有帮助。查询需要10秒,这太多了。
....
131 rows in set (10.25 sec)
mysql> explain SELECT results.event from results
INNER JOIN events ON results.event=events.id
where (DATEDIFF(NOW(), events.startdate) < 30)
AND (DATEDIFF(NOW(), events.startdate) > -1)
AND results.status='OK'
group by events.id;
+----+-------------+---------+--------+----------------------------------------------+------------+---------+-----------------------+--------+---------------------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+--------+----------------------------------------------+------------+---------+-----------------------+--------+---------------------------------------------------------------------+
| 1 | SIMPLE | results | ref | idx_event,idx_status | idx_status | 53 | const | 773425 | Using index condition; Using where; Using temporary; Using filesort |
| 1 | SIMPLE | events | eq_ref | PRIMARY,idx_events_name,idx_events_startdate | PRIMARY | 4 | eventor.results.event | 1 | Using where |
+----+-------------+---------+--------+----------------------------------------------+------------+---------+-----------------------+--------+---------------------------------------------------------------------+
2 rows in set (0.01 sec)
答案 0 :(得分:5)
在函数中包装索引列会阻止优化程序使用它。看起来您需要在startdate上释放索引以获得JOIN的漂亮过滤结果集:
SELECT r.event from results
JOIN events e
ON e.id = r.event
AND e.startdate > CURDATE() - INTERVAL 30 DAY
AND e.startdate < CURDATE() + INTERVAL 1 DAY
WHERE r.status = 'OK'
我喜欢将我的联接表条件放在ON子句中,并尽可能使用表别名。
我还希望将整数状态列添加到字符串“确定”,如果需要,可以将其外键加到状态表中。
另外,我还想使用>=
和<
作为日期范围,例如,startdate
是DATETIME
或{{1} },如果TIMESTAMP
处于2014-08-01 00:00:00
的截止位置,此查询将排除CURDATE() - INTERVAL 30 DAY
的值。