Mysql查询优化 - 非常慢

时间:2016-06-15 06:31:34

标签: mysql query-optimization

我需要优化运行速度非常慢的查询,但不知道该怎么做。它包含一个子查询,使其非常慢。如果我删除内联查询,那么它运行得很好。

查询是:

EXPLAIN
SELECT  t.service_date, 
        t.service_time, 
        (SELECT js.modified_date FROM rej_job_status js WHERE js.booking_id=b.booking_id ORDER BY id DESC LIMIT 1) `cancel_datetime`, 
        b.booking_id, 
        b.ref_booking_id, 
        b.phone, b.city, 
        b.booking_time, 
        CONCAT(rc.firstname," ",rc.lastname) customer_name, 
        rc.phone_no, 
        rs.service_id,
        rs.service_name,
        rct.city_name 
FROM rej_job_details t 
JOIN rej_booking b ON t.booking_id = b.booking_id 
JOIN rej_customer rc ON rc.customer_id = b.customer 
JOIN rej_service rs ON t.service_id = rs.service_id 
JOIN rej_city rct ON rct.city_id=b.city 
WHERE t.act_status = 0 AND DATE(b.booking_time) >= '2016-06-01' 
        AND DATE(b.booking_time) <= '2016-06-14' 
ORDER BY b.booking_time DESC 
LIMIT 0 , 50 

解释计划显示了这一点:

id  select_type         table   type    possible_keys       key         key_len ref                         rows    Extra   
1   PRIMARY             b       ALL     PRIMARY             NULL        NULL    NULL                        32357   Using where; Using filesort
1   PRIMARY             rct     eq_ref  PRIMARY             PRIMARY     4       crmdb.b.city        1       NULL
1   PRIMARY             t       ref     booking_id          booking_id  4       crmdb.b.booking_id  1       Using where
1   PRIMARY             rs      eq_ref  PRIMARY,service_id  PRIMARY     4       crmdb.t.service_id  1       NULL
1   PRIMARY             rc      eq_ref  PRIMARY             PRIMARY     4       crmdb.b.customer    1       Using where 
2   DEPENDENT SUBQUERY  js      index   NULL                PRIMARY     4       NULL                        1       Using where

a)如何阅读本解释计划并了解其含义?

b)如何优化此查询?

2 个答案:

答案 0 :(得分:0)

要理解完整的explain - 计划,你应该阅读documentation,但它包含的最重要的信息是mysql使用的索引,或者,通常更具启发性,它不使用

对于您的DEPENDENT SUBQUERY(即您的“内联查询”),它不会使用良好的索引,这会使您的查询变慢,因此您需要在表格上添加索引rej_job_status(booking_id) rej_job_status

创建,测试并再次检查您的explain计划,然后应该在key下列出DEPENDENT SUBQUERY下的新索引。

另一种优化可能是为您的表rej_booking(booking_time)添加索引rej_booking。它取决于你的数据,如果它改进了查询,但你应该尝试,因为现在,mysql不使用索引进行选择。

答案 1 :(得分:0)

booking_time隐藏在函数中,因此无法使用INDEX(booking_time)。这导致了昂贵的表扫描。

AND DATE(b.booking_time) >= '2016-06-01' 
AND DATE(b.booking_time) <= '2016-06-14' 

- &GT;

AND b.booking_time >= '2016-06-01' 
AND b.booking_time <  '2016-06-15' -- note 3 differences in this line

或者,这可能更简单(通过避免第二次日期计算):

AND b.booking_time >= '2016-06-01' 
AND b.booking_time <  '2016-06-01' + INTREVAL 2 WEEK

EXPLAIN中,我希望'ALL'成为'范围','Fileort'将消失。