MySQL實戰 | 11 怎麼給字符串字段加索引?

兩種:

  • 全字段索引
  • 前綴索引

舉例:

mysql> create table SUser(
ID bigint unsigned primary key,
email varchar(64), 
... 
)engine=innodb; 

可以對 email 字段創建全字段索引,或者前綴索引。

mysql> alter table SUser add index index1(email);
或
mysql> alter table SUser add index index2(email(6));

區別

全字段索引

前綴索引

1、全字段索引佔用空間大,前綴索引佔用空間小;
2、全字段索引查詢效率高,前綴索引則會增加額外的記錄掃描次數。

執行過程

select id,name,email from SUser where email='[email protected]';

1、全字段索引

① 從 index1 索引樹中找到索引值是 [email protected] 的記錄,然後得到主鍵值;
② 根據主鍵值獲取到該行的完整數據(回表),再判斷 email 是否滿足條件,將這行記錄加入結果集;
③ 沿着索引樹繼續查找下一條滿足條件的數據,若不滿足,循環結束;

2、前綴索引

① 從 index2 索引樹上查找索引值是 zhangs 的記錄,找到一條後,得到主鍵值;
② 根據主鍵值獲取到該行的完整數據(回表),再判斷 email 是否滿足條件,將這行記錄加入結果集;
③ 沿着索引樹繼續查找下一條滿足條件的數據,發現仍然滿足條件,重複上面的操作;
④ 重複上一步,直到在 index2 上取到的值不滿足條件,循環結束。

很明顯,使用前綴索引,導致查詢次數增多。

如何減少前綴索引查詢次數?

區分度,區分度越高,前綴重複的可能性越小,進而,查詢次數就越少。

通過如下語句,可以查詢到不通前綴長度,分別有多少個不同的值:

mysql> select 
  count(distinct email) as L
  count(distinct left(email,4)as L4,
  count(distinct left(email,5)as L5,
  count(distinct left(email,6)as L6,
  count(distinct left(email,7)as L7,
from SUser;

自己可以預先設定一個可以接受的重複比例,比如大於 L * 95%。

前綴索引對覆蓋索引的影響

使用前綴索引將無法利用覆蓋索引的優化。

查詢時,系統並不確定前綴索引的定義是否截斷了完整信息。

前綴索引的優化

1、倒序存儲

適合字段值前面部分重複度高,後半部分重複度低,這時可以倒序存儲數據。

查詢時可以這麼寫:

mysql> select field_list from t where id_card = reverse('input_id_card_string');

2、做 hash

新增一個字段,專門存儲字段的 hash 值:

mysql> alter table t add id_card_crc int unsigned, add index(id_card_crc);

每次插入數據時,都要調用 crc32() 這個函數得到校驗碼填到這個新字段。

這個字段有可能重複,需要聯合判斷 id_card 的值是否精確相同。

mysql> select field_list from t where id_card_crc=crc32('input_id_card_string') and id_card='input_id_card_string'

二者的區別

1、都不支持範圍查詢
2、hash 字段需要額外的空間
3、CPU 消耗:倒序插入時需要額外調用 reverse 函數,hash 需要調用 crc32() 函數。reverse 函數消耗的 CPU 更小一些;
4、hash 字段方式的查詢效率更高,因爲計算出來的 hash 值重複的可能性較小,掃描次數接近於 1

總結

1、直接創建完整索引,這樣可能比較佔用空間;
2、創建前綴索引,節省空間,但會增加查詢掃描次數,並且不能使用覆蓋索引;
3、倒序存儲,再創建前綴索引,用於繞過字符串本身前綴的區分度不夠的問題;
4、創建 hash 字段索引,查詢性能穩定,有額外的存儲和計算消耗,跟第三種方式一樣,都不支持範圍掃描。

如何選擇?

當數據量大時,一個學校每年預估 2 萬新生,50 年才 100 萬記錄,能節省多少空間,直接全字段索引。省去了開發轉換及侷限性風險,碰到超大量迫不得已再用後兩種辦法。從業務量預估優化和收益,這不失爲一個不錯的想法。


你的關注是對我最大的鼓勵!

關注本公衆號,後臺回覆「2018」即可獲取傳智播客 2018 最新 Python 和 Java 教程。

公衆號提供CSDN資源免費下載服務!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章