# MySQL系列 - 創建高性能索引

索引的分類

索引分爲B-Tree索引、哈希索引、空間索引、全文索引、其他等索引。

在 MySQL 中,最常用的是 B-Tree 索引(也就是我們常說的B+樹索引,這裏B-Tree索引只是一個分類)

索引的優點

  • 索引大大減少了服務器需要掃描的數據量

  • 索引可以幫助服務器避免排序和臨時表

  • 索引可以將隨機I/O變成順序I/O

創建高性能索引

下面根據不同的情況來說明,如何創建合適並且高性能的索引來提高索引效率。

  • 獨立的列

如果查詢中的列不是獨立的,則 MySQL不會使用索引。

所謂獨立的列指的是,查詢中的列不能是表達式的一部分,要是獨立的,舉例如下

select * from t_user where id + 1 = 9;

在上面的查詢語句,查詢中的列 id 不是獨立的,而是表達式 id + 1 的一部分,因此索引不會生效

關於索引失效的各種情況,詳情參考 MySQL索引失效總結

  • 前綴索引

有時候需要很長的字符列,這會讓索引變得大且慢。

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

當然,選擇的部分字符不合適會導致過濾效果很差,所以一定要選擇區分度較高的前綴建立索引。

創建前綴索引腳本如下:

alter table t_user add key (address(10));

該腳本表示以地址的前10個字符創建索引。

  • 多列索引

很多人對多列索引理解不夠,爲多個列創建獨立的索引,或者按照錯誤的順序創建多列索引。

在多個列上建立獨立的索引,一般情況下並不能提高MySQL的性能,正確的做法是,根據 where 條件的情況,在多個列上建立組合索引。

使用多列索引,查詢條件必須滿足最左前綴原則,也就是說,where 條件的順序與組合索引字段的順序要保持一致。

比如我們在字段1和字段2上建立組合索引,而查詢條件只有字段2,此時並不會走索引進行查詢。

  • 覆蓋索引

索引確實是一種查找數據的高效方式,但是 MySQL 也可以直接使用索引獲取列的數據,這樣就不再需要讀取數據行了。

如果一個索引包含所有需要查詢的字段的值,我們就稱之爲 覆蓋索引

比如我們要查詢用戶的角色,一個用戶會有多種角色,通常我們在 用戶ID和角色ID 建立一個索引,這樣我們查詢用戶的角色ID列表的時候,直接可以通過索引返回,不需要再回表。

  • 利用索引進行排序

當索引的順序和 ORDER BY 子句的順序完全一致,並且所有列的排序方向都一樣時,MySQL 能夠使用索引來對結果做排序。

比如,我們經常需要根據創建時間進行排序,那麼在創建時間字段上建立一個索引,在進行排序查詢的時候就會高效很多。

當 ORDER BY 子句不滿足索引的最左前綴的要求時,就無法利用索引進行排序。

當然,特殊情況,也就是說,假如 ORDER BY 子句是從索引的第二個字段開始,但是索引的第一個字段被至指定爲常數,也可以用於查詢排序。

  • 創建區分度高的索引

比如,用戶性別,我們知道性別取值一般是 男和女 ,也就兩個值,重複率很高,如果在性別字段上創建索引,那麼索引的效率就很低。

再比如,用戶身份證號,每個人的身份證號都是不同的,在身份證號字段上建立索引,區分度就非常,根據身份證號索引的效率就很高。

總結

在選擇索引和編寫利用這些索引的查詢時,需要根據具體業務情況來定,沒有萬能的方法。不過一般我們需要記住下面幾個原則:

  • 單行訪問是很慢的。如果服務器從存儲中讀取一個數據塊只是爲了獲取某一行數據,那麼就浪費了很多工作。最好讀取的數據塊中包含儘可能多的數據行。

  • 按順序訪問範圍數據是很快的。原因是:第一,順序I/O不需要多次磁盤尋道,比隨機I/O要快得多;第二,如果服務器能按順序讀取數據,那麼就不需要額外進行排序操作了。

  • 索引覆蓋查詢時很快的。如果一個索引包含了查詢需要的所有列,那麼存儲引擎就不需要再回表查找數據行了。

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