如何优化SQL查询?密钥未被使用

时间:2014-08-18 19:52:15

标签: mysql sql performance optimization

如何优化以下查询?我试图创建索引(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)

1 个答案:

答案 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子句中,并尽可能使用表别名。

我还希望将整数状态列添加到字符串“确定”,如果需要,可以将其外键加到状态表中。

另外,我还想使用>=<作为日期范围,例如,startdateDATETIME或{{1} },如果TIMESTAMP处于2014-08-01 00:00:00的截止位置,此查询将排除CURDATE() - INTERVAL 30 DAY的值。