查一次left?join沒有走索引以及原因分析
查一次left join沒有走索引的原因
線上有個查詢sql,原來是inner join 查詢沒有問題,后來應(yīng)業(yè)務(wù)要求改成left join之后, 查詢時間就暴漲了 需要長達24s
通過explain分析,發(fā)現(xiàn)訂單表沒有走索引 ,分析之后解決了,記錄下來。
為了簡潔起見,這里就將無關(guān)的查詢字段都用*
具體sql如下
SELECT * from t_item_detail a left join t_order_detail d on a.order_code=d.order_code left join t_connection b on a.unique_code = b.funds_unique left join t_capital_detail c on b.capital_unique = c.unique_code where item_receipt_disbursement=1 and a.is_deleted=0 and order_type_code=00901 group by a.unique_code LIMIT 10
用explain命令分析如下
發(fā)現(xiàn)table d 的type為all, rows居然高達20萬行 。
d對應(yīng)的表為order_detail 表,type為all 說明并沒有走索引。
這里首先看關(guān)聯(lián)條件
from t_item_detail a left join t_order_detail d on a.order_code=d.order_code
該條件并無問題,然后這兩張表的order_code字段是否加索引.
兩張表的order_code字段均有索引。
其次再看, 如果兩個字段或者兩張表的編碼不同,也會導(dǎo)致索引失效。
但是這兩張表的編碼和字段編碼也均相同,因此也排除掉。
最后發(fā)現(xiàn),
如果寫成
explain SELECT * from t_item_detail a left join t_order_detail d on a.order_code=d.order_code and d.order_type_code=00901 left join t_connection b on a.unique_code = b.funds_unique left join t_capital_detail c on b.capital_unique = c.unique_code where item_receipt_disbursement=1 and a.is_deleted=0 group by a.unique_code LIMIT 10
也就是將原來在where條件的order_type_code=00901 寫到left join的條件后面
d的索引就生效了,所有的索引都生效了。
查詢時間也從原來的24秒 變成了不到1秒。
這是為什么呢?
其實問題就出在這個 d.order_type_code=00901 這個條件上
當(dāng)有這個條件時候
全文掃描
沒有這個條件的時候
從sql的執(zhí)行順序來分析:
SELECT * from t_item_detail a left join t_order_detail d on a.order_code=d.order_code left join t_connection b on a.unique_code = b.funds_unique left join t_capital_detail c on b.capital_unique = c.unique_code where item_receipt_disbursement=1 and a.is_deleted=0 and order_type_code=00901 group by a.unique_code LIMIT 10
這里面的執(zhí)行順序為
- 1.
from
- 2.
on
- 3.
join
- 4.
where
- 5.
select
- 6.
group by
- 7.
limit
即
寫的順序:select … from… where… group by… having… order by… limit [offset,](rows)
執(zhí)行順序:from… where…group by… having… select … order by… limit
知道這個,我們再看這個sql
不走索引 有order_type_code條件
SELECT * from t_item_detail a left join t_order_detail d on a.order_code=d.order_code left join t_connection b on a.unique_code = b.funds_unique left join t_capital_detail c on b.capital_unique = c.unique_code where item_receipt_disbursement=1 and a.is_deleted=0 and order_type_code=00901 group by a.unique_code LIMIT 10
和
走索引 沒有order_type_code條件
SELECT * from t_item_detail a left join t_order_detail d on a.order_code=d.order_code left join t_connection b on a.unique_code = b.funds_unique left join t_capital_detail c on b.capital_unique = c.unique_code where item_receipt_disbursement=1 and a.is_deleted=0 group by a.unique_code LIMIT 10
和走索引有沒有order_type_code條件
SELECT * from t_item_detail a left join t_order_detail d on a.order_code=d.order_code and d.order_type_cod=‘00901' left join t_connection b on a.unique_code = b.funds_unique left join t_capital_detail c on b.capital_unique = c.unique_code where item_receipt_disbursement=1 and a.is_deleted=0 group by a.unique_code LIMIT 10
會發(fā)現(xiàn) 在不走索引有order_type_code條件的那個sql中, 在執(zhí)行到where的時候,需要去找到條件 order_type_code=00901 ,但是order_type_code這個字段沒有索引,所以數(shù)據(jù)庫就去對order_detail進行全表掃描。
因此解決方案
就是給order_type_code加上索引,或者給 left join on就加上條件order_type_code=xxx ,直接過濾掉
因此,謹記,大表查詢的時候,where 的條件千萬記得加上索引?。。。?/p>
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
MySQL 啟動報錯:File ./mysql-bin.index not found (Errcode: 13)
這篇文章主要介紹了MySQL 啟動報錯:File ./mysql-bin.index not found (Errcode: 13)的解決方法,需要的朋友可以參考下2014-07-07MySql逗號分割的字段數(shù)據(jù)分解為多行代碼示例
逗號分割的字符串可以作為分組數(shù)據(jù)的標識符,用于對數(shù)據(jù)進行分組和聚合操作,下面這篇文章主要給大家介紹了關(guān)于MySql逗號分割的字段數(shù)據(jù)分解為多行的相關(guān)資料,需要的朋友可以參考下2023-12-12Linux操作系統(tǒng)操作MySQL常用命令小結(jié)
本文給大家分享Linux操作系統(tǒng)操作MySQL常用命令小結(jié),需要的朋友參考下吧2017-07-07