MySQL優化——or條件優化


    MySQL5.0和更新版本中引入了一種叫:索引合並(Index merge)的策略,一定程度上可以使用表上多個單列索引來定位指定的行。

    該特性主要應用於以下三種場景:

      1. 對or語句求並集,如查詢select * from film_actor where c1 = "xxx" or c2 = "xxx"時,如果c1和c2列上分別有索引,可以按照c1和c2條件進行查詢,再將查詢結果合並(union)操作,得到最終結果。

      2. 對and語句求交集,如查詢select * from film_actor where c1 = "xxx" and c2 = "xxx"時,如果c1和c2列上分別有索引,可以按照c1和c2條件進行查詢,再將查詢結果取交集(intersect)操作,得到最終結果。

      3. 組合前兩種情況的合並及相交。

    該新特性可以在一些場景中大幅度提升查詢性能,但受限於MySQL糟糕的統計信息,也導致很多查詢場景查詢性能極差甚至導致數據庫崩潰。

      以select * from film_actor where c1 = "xxx" and c2 = "xxx"為例:

        1. 當c1列和c2列選擇性較高時,按照c1和c2條件進行查詢性能高且返回數據集較小,再對兩個數據量較小的數據集求交集的操作成本也比較低,最終整個語句查詢高效;

        2. 當c1列或c2列選擇性較差且統計信息不准時,比如整表數據量1000萬,按照c2列條件返回800萬數據,按照c1列返回100條數據,此時按照c2列條件進行索引掃描+聚集索引查詢的操作成本極高(可能是整表掃描的百倍消耗),對100

          條數據和800萬數據求交集的成本也極高,最終導致整條SQL需要消耗大量CPU和IO資源,且相應時間超長,而如果值使用c1列的索引,查詢消耗資源少且性能較高。

          即使用select * from film_actor where c1 = "xxx" union all select * from film_actor where  c2 = "xxx"往往更好。

      索引合並策略有時候是一種優化的結果,但實際上更多的時候說明了表上的索引建的的很糟糕:

        1、當出現服務器對多個索引做相交操作時(通常有多個and條件),通常意味着需要一個包含所有相關列的多列索引,而不是多個獨立的單列索引。

        2、當服務器需要對多個索引做合並操作時(通常有多個or條件),通常需要消耗大量cpu和內存資源在算法緩存、排序和合並操作上。特別是當其中某些索引的選擇性不高,需要合並掃描返回的大量數據的時候。

        3、更重要的是,優化器不會把這些計算到“查詢成本”中,優化器只關心隨機頁面讀取。這回使得查詢的成本被“低估”,導致該執行計划還不如直接走全表掃描。

        


免責聲明!

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



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