2016-06-15 5 views
0

私は非常に遅く実行されているクエリを最適化する必要がありますが、それを行う方法はわかりません。それは非常に遅くなっているサブクエリを含んでいます。インラインクエリを削除すると、非常にうまく動作します。MySQLクエリの最適化 - 非常に遅い

クエリは次のとおりです。

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)このクエリを最適化するにはどうすればよいですか?

答えて

0

explain -planを理解するには、documentationを読んでください。もっとも重要な情報には、mysqlが使用するインデックス、または通常はそれが使用しないインデックスがあります。あなたのDEPENDENT SUBQUERYのために

あなたがテーブルの上にrej_job_statusインデックスrej_job_status(booking_id)を追加する必要がありますので、(それがあなたの「インラインクエリ」である)、それは、あなたのクエリが遅くなります良い指標を、使用していません。

これを作成してテストし、explainプランをもう一度確認すると、新しいインデックスがDEPENDENT SUBQUERYkeyに表示されます。

さらにrej_booking(booking_time)というインデックスをテーブルrej_bookingに追加することもできます。クエリが改善された場合はデータに依存しますが、今はmysqlがその選択肢のインデックスを使用していないので、試してみてください。

0

booking_timeは関数内に隠れているので、INDEX(booking_time)は使用できません。これはコストのかかるテーブルスキャンにつながります。

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

- >

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

それとも、これは(第2日付計算避けることにより)単純かもしれません:EXPLAIN

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

を、私は 'ALL' になることを期待します'range'、 'Filesort'が消えます。