「MySQL高級篇」explain分析SQL,索引失效&&常見優化場景( 三 )

1. 不滿足最左前綴所謂最左前綴 , 可以想象成一個爬樓梯的過程,假設我們有一個復合索引:name , status,address,那這個樓梯由低到高依次順序是:name,status,address,最左前綴 , 要求我們不能出現跳躍樓梯的情況 , 否則會導致我們的索引失效:?

  1. 按樓梯從低到高,無出現跳躍的情況--此時符合最左前綴原則,索引不會失效

「MySQL高級篇」explain分析SQL,索引失效&&常見優化場景

文章插圖
  1. 出現跳躍的情況
  • 直接第一層name都不走,當然都失效

「MySQL高級篇」explain分析SQL,索引失效&&常見優化場景

文章插圖
  • 走了第一層,但是后續直接第三層,只有出現跳躍情況前的不會失效(此處就只有name成功)

「MySQL高級篇」explain分析SQL,索引失效&&常見優化場景

文章插圖
  • 同時,這個順序并不是由我們where中的排列順序決定,比如:
    • where name='小米科技' and status='1' and address='北京市'
    • where status='1' and name='小米科技' and address='北京市'
這兩個盡管where中字段的順序不一樣,第二個看起來越級了,但實際上效果是一樣的
其實是因為我們MySQL有一個Optimizer(查詢優化器) , 查詢優化器會將SQL進行優化,選擇最優的查詢計劃來執行 。
2. 范圍查詢之后范圍查詢之后的索引字段,會失效?。?!但迸f磧美捶段Р檠哪歉鏊饕侄我廊揮行?,壤_賈械膕tatus 。
  • 而圖中address失效了,對比一下長度便可看出來 。

「MySQL高級篇」explain分析SQL,索引失效&&常見優化場景

文章插圖
3. 索引字段做運算對索引字段做運算,使用函數等都會導致索引失效 。
「MySQL高級篇」explain分析SQL,索引失效&&常見優化場景

文章插圖
4. 字符串不加' '索引字段為字符串類型,由于在查詢時,沒有對字符串加單引號,MySQL的查詢優化器,會自動的進行類型轉換 , 造成索引失效 。
5. 避免select *危害
  • 消耗更多的 CPU 和 IO 以網絡帶寬資源
  • 可減少表結構變更帶來的影響
  • 無法使用覆蓋索引
覆蓋索引盡量使用覆蓋索引(索引列完全包含查詢列),減少select *?
當查詢列中包含了非索引項 , 雖然我們還是能夠利用到索引 , 但是為了獲取非索引項字段 , 我們需要回表去查詢數據,效率會比較低 。?
6. or分割開的條件用or分割開的條件,如果or前的條件中的列有索引 , 而后面的列中沒有索引 , 那么涉及的索引都不會被用到 。?
示例,name字段是索引列,而createtime不是索引列,中間是or進行連接是不走索引的 :
  • 因為有一個不走索引,又是or條件,兩個都要判斷一下,相當于不管如何,都還是得去走全表查詢,沒有利用到索引 。
explain select * from tb_seller where name='黑馬程序員' or createtime = '2088-01-01 12:00:00'\G;
「MySQL高級篇」explain分析SQL,索引失效&&常見優化場景

文章插圖
7. 以%開頭的Like模糊查詢可以聯系字典樹Trie的匹配吧 。
  • 比如要找‘abc’ , 如果是%bc , 一開始的根都找不到了,自然沒辦法利用到索引樹
  • 而如果是ab%,還能利用到前兩個 。
  • %開頭的失效 , %結尾的還能利用索引(實際上這里就相當于字符串的最左前綴原則 , 可以這么理解)

「MySQL高級篇」explain分析SQL,索引失效&&常見優化場景

文章插圖
解決方法:使用覆蓋索引當真的需要兩邊都使用%來模糊查詢時,只有當 作為模糊查詢的條件字段(例子中的name)以及 想要查詢出來的數據字段(例子中的 name & status & address)都在索引列上時,才能真正使用索引 。
關于覆蓋索引,可以參考這篇 -> 索引原理,設計原則

「MySQL高級篇」explain分析SQL,索引失效&&常見優化場景

文章插圖
8. MySQL認為全表更快
「MySQL高級篇」explain分析SQL,索引失效&&常見優化場景

文章插圖
此處是由于數據的特殊性,‘北京市’所占的比例很高,還不如全表掃描
「MySQL高級篇」explain分析SQL,索引失效&&常見優化場景

文章插圖
8.1 is null 和 is not null
本質上跟上邊是一樣的

推薦閱讀