mysql重復索引、冗余索引、未使用索引的定義和查找


1.冗余和重復索引

  mysql允許在相同列上創建多個索引,無論是有意還是無意,mysql需要單獨維護重復的索引,並且優化器在優化查詢的時候也需要逐個地進行考慮,這會影響性能。重復索引是指的在相同的列上按照相同的順序創建的相同類型的索引,應該避免這樣創建重復所以,發現以后也應該立即刪除。但,在相同的列上創建不同類型的索引來滿足不同的查詢需求是可以的。

 

  冗余索引和重復索引有一些不同,如果創建了索引(a,b),再創建索引(a)就是冗余索引,因為這只是前面一個索引的前綴索引,因此(a,b)也可以當作(a)來使用,但是(b,a)就不是冗余索引,索引(b)也不是,因為b不是索引(a,b)的最左前綴列,另外,其他不同類型的索引在相同列上創建(如哈希索引和全文索引)不會是btree索引的冗余索引。

 

  另外:對於二級索引(a,id),id是主鍵,對於innodb來說,主鍵列已經包含在二級索引中了,所以這個也是冗余索引。大多數情況下都不需要冗余索引,應該盡量擴展已有的索引而不是創建新索引,但也有時候處於性能方面的考慮需要冗余索引,因為擴展已有的索引會導致其變得太大,從而影響其他使用該索引的查詢性能。如:如果在整數列上有一個索引,現在需要額外增加一個很長的varchar列來擴展該索引,那么性可能會急劇下降,特別是有查詢把這個索引當作覆蓋索引,或者這是myisam表並且有很多范圍查詢的時候(由於myisam的前綴壓縮)。

 

如:表userinfo,myisam引擎,有100W行記錄,每個state_id值大概2W行,在state_id列有一個索引對下面的查詢有用:如:select count(*) from userinfo where state_id=5;測試每秒115次QPS

 

對於下面的查詢這個state_id列的索引就不太頂用了,每秒QPS是10次

select state_id,city,address from userinfo where state_id=5;

 

  如果把state_id索引擴展為(state_id,city,address),那么第二個查詢的性能更快了,但是第一個查詢卻變慢了,如果要兩個查詢都快,那么就必須要把state_id列索引進行冗余了。但如果是innodb表,不冗余state_id列索引對第一個查詢的影響並不明顯,因為innodb沒有使用索引壓縮,myisam和innmodb表使用不同的索引策略的select查詢的qps測試結果(以下測試數據僅供參考):

                    只有state_id列索引    只有state_id_2索引    同時有兩個索引

myisam,第一個查詢    114.96                25.40                112.19

myisam,第二個查詢    9.97                  16.34                16.37

innodb,第一個查詢    108.55                100.33               107.97

innodb,第二個查詢    12.12                 28.04                28.06

 

從上圖中可以看出,兩個索引都有的時候,缺點是成本更高,下面是在不同的索引策略時插入innodb和myisam表100W行數據的速度(以下測試數據僅供參考):

                                                  只有state_id列索引    同時有兩個索引

innodb,對有兩個索引都有足夠的內容的時候       80秒                136秒

myisam,只有一個索引有足夠的內容的時候        72秒                470秒

 

  可以看到,不論什么引擎,索引越多,插入速度越慢,特別是新增索引后導致達到了內存瓶頸的時候。解決冗余索引和重復索引的方法很簡單,刪除這些索引就可以了,但首先要做的是找出這樣的索引,可以通過一些復雜的訪問information_schema表的查詢來找,不過還有兩個更簡單的方法,使用:shlomi noach的common_schema中的一些視圖來定位,也可以使用percona toolkit中的pt-dupulicate-key-checker工具,該工具通過分析表結構來找出冗余和重復的索引,對於大型服務器來說,使用外部的工具更合適,如果服務器上有大量的數據或者大量的表,查詢information_schema表可能會導致性能問題。建議使用pt-dupulicate-key-checker工具。

 

在刪除索引的時候要非常小心:

  如果在innodb引擎表上有where a=5 order by id 這樣的查詢,那么索引(a)就會很有用,索引(a,b)實際上是(a,b,id)索引,這個索引對於where a=5 order by id 這樣的查詢就無法使用索引做排序,而只能使用文件排序了。所以,建議使用percona工具箱中的pt-upgrade工具來仔細檢查計划中的索引變更。

 

2. 未使用的索引

除了冗余索引和重復索引,可能還會有一些服務器永遠不使用的索引,這樣的索引完全是累贅,建議考慮刪除,有兩個工具可以幫助定位未使用的索引:

  A:在percona server或者mariadb中先打開userstat=ON服務器變量,默認是關閉的,然后讓服務器運行一段時間,再通過查詢information_schema.index_statistics就能查到每個索引的使用頻率。

  B:使用percona toolkit中的pt-index-usage工具,該工具可以讀取查詢日志,並對日志中的每個查詢進行explain操作,然后打印出關羽索引和查詢的報告,這個工具不僅可以找出哪些索引是未使用的,還可以了解查詢的執行計划,如:在某些情況下有些類似的查詢的執行方式不一樣,這可以幫助定位到那些偶爾服務器質量差的查詢,該工具也可以將結果寫入到mysql的表中,方便查詢結果。


免責聲明!

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



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