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

Mar*_*son 0 mysql sql optimization performance

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

Art*_*rth 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'
Run Code Online (Sandbox Code Playgroud)

我喜欢将我的连接表条件放在ON子句中,并尽可能使用表别名.

我也更喜欢整数状态列到字符串'OK',如果需要,可以将其外键到具有描述的状态表.

作为一个补充说明..我也喜欢使用>=<日期范围,例如,如果startdateDATETIMETIMESTAMP,此查询将排除值,2014-08-01 00:00:00如果它是在切断CURDATE() - INTERVAL 30 DAY.