MySQL 字首索引——讓索引減負狂奔

zhoupq發表於2017-04-09

什麼是字首索引

  我們吃甘蔗的時候,若出現蟲蛀情況,我們不能判斷蟲蛀的範圍有大,如果為了省事,直接砍去若干節,蟲蛀殘留的概率就會小很多,但是很可能損失更多的可食用甘蔗。如果一點點地削,直至蟲蛀不再出現為止,看起來多花了點功夫,但是浪費的少,也只值得。

  相比於砍甘蔗,MySQL 的全文索引類似於第一種方法,字首索引則像是第二種方法。

  當需要以某個資料型別是字串的列為索引時,通常都是建立全文索引,通過全文匹配條件來篩選記錄。其實沒有必要,一種更好的辦法是:

可以索引開始的部分字元,這樣可以大大節約索引空間,從而提高索引效率

為什麼要使用字首索引

  • 大大節約索引空間,從而提高索引效率
  • 對於 BOLBTEXT 或者很長的 VARCHAR 型別的列,必須使用字首索引。因為 MySQL 不允許索引這些列的完整長度

索引的選擇性

  也許我們心中已經留下了字首索引效率高於全文索引的印象,但是字首的長度該保留多少呢?有沒有一個標準的值呢?換句話說,索引的長度與查詢效率之間呈現怎樣的關係?

  首先,引入一個概念——索引的選擇性:

不重複的索引值(也稱基數)和資料表記錄總數(#T)的值,範圍從 1 / #T 到 1 之間。

  索引的選擇性越高則查詢效率越高,因為選擇性高的索引可以讓 MySQL 在查詢時過濾掉更多的行。對比之下,唯一索引(值唯一,比如主鍵)的選擇性是 1,這是最好的索引選擇性,效能也是最好的。

  字首索引會降低索引的選擇性,因為使用字首索引查詢出的基數很難完美匹配 #T,但是比起這些缺點,字首索引的好處簡直是大過天。

  真正的難點在於:要選擇足夠長的字首以保證較高的選擇性,同時又不能太長。字首的長度應該使字首索引的選擇性接近索引整個列,即字首的“基數”應該接近於完整列的“基數”。

舉例說明

  下面的例子,查詢軟體名稱,並統計其數量

MySQL 字首索引——讓索引減負狂奔
統計 #T

  第一列的統計數量則可認為是 #T,現在要查詢到最頻繁出現(基數接近 #T )的軟體名稱字首,直接從 7 個字首字母開始:

MySQL 字首索引——讓索引減負狂奔
字首長度為 7 索引

  每個字首都比原來的軟體名稱出現的次更多,因此唯一字首比唯一軟體名稱要少得多。然後我們增加字首長度,直到這個字首的選擇性接近完整列的選擇性,此時的字首長度為 9

MySQL 字首索引——讓索引減負狂奔
字首長度為 9 索引

  試過 10,和 9 差不多,最後,選擇了字首長度為 9 的索引。   

  我的部落格地址:MySQL 高效能索引之字首索引

相關文章