order by 執行計划索引使用不同的坑


案例場景

表數據量7000+萬,其中滿足如下條件的數據量約為:1200條。走主鍵索引的查詢未必是最優的。見如下案例:

#表索引說明

 

案例分析

 分別查看sql的執行計划

1、無limit 、無order by

2、limit 2000

3、order by id,add_time limit 2000

4、order by id limit 2000

     從執行計划來看,order by id limit 2000 時候,mysql查詢引擎遍歷的rows最小為4萬(其他均為3000+萬)甚至order by id,add_time 時還出現了 filesort,表面看來

order by id limit 2000時候,應該是最理想的查詢方式。可實際執行起來恰恰相反。

 

案例總結

1.走主鍵索引的場景(order by id limit 2000)

  表明通過id 索引 根據索引樹從最右側葉子節點依次按順序獲取n條與where條件進行過濾,直到獲取2000條數據,並沒有真正通過id作為條件去篩選數據,而是用where條件篩選,由於根據id 順序匹配數據,如果該數據不滿足where會繼續獲取,直到滿足2000條,這樣就會導致訪問數據量過大。極端情況如果第2000條數據為表的最后一條數據,則會掃描全表。

  可理解 執行順序是:order by  --> where--> limit

 

2.走組合索引的場景(order by id,add_time limit 2000)

  使用limit 時執行計划會使用組合索引,進行條件篩選,在Extra中顯示Using index condition;Using where ;Using filesort;  優化器首先解析索引列;通過索引列(union_2)找出表中行數據,在獲取其他where條件進行篩選(索引向下),獲取到與條件匹配行后進行order by排序,由於沒有使用排序索引索引使用了Using filesort進行文件排序,【一般情況下文件排序會導致增加消耗,查詢時緩慢,不過不能一概而論】,最后根據limit 獲取指定行數

  可理解 執行順序是:where --> order by --> limit

 

  每個索引在數據庫中都是一個索引樹,其數據節點存儲了指向實際數據的指針,如果用一個索引來查詢,其原理就是從索引樹上去檢索,並獲得這些指針,然后去取出數據,如果通過一個索引(id),得到過濾后的指針,這時,你的另一個條件索引(union_2)如果再過濾一遍,將得到2組指針的集合,如果這時候取交集(order by id 場景),未必就很快,因為如果每個集合都很大的話,取交集的時候,等於掃描2個集合,效率會很低,所以沒法用2個索引。

  當然有時候mysql會考慮臨時建立一個聯合索引,將2個索引聯合起來用,但是並不是每種情況都能奏效,同樣的道理,用一個索引檢索出結果集之后,排序時,也無法用上另一個索引了(order by id,add_time 場景)。

  最后在不同情況下優化器選擇索引不同,優化需根據不同場景進行優化,我們也需要根據不同的場景創建最優的索引。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM