天天看點

淺談MySQL原理與優化(三)—— 索引

索引是資料庫中的一種非常重要的存儲結構。優秀的索引對于資料庫性能有着很大的提升。索引的英文是index。這個詞最早的含義是書的目錄。類似于下圖的樣子。

淺談MySQL原理與優化(三)—— 索引
一本書有很多頁,當我們想找一個内容的時候其實是很費時費力的,但是當我們有了索引目錄以後,通過每一條索引記錄中關鍵詞和頁碼的對應關系,我們就可以更快的找到想要的内容。
淺談MySQL原理與優化(三)—— 索引

為了加快查找速度,索引記錄一定是按關鍵詞順序排列的,而且我們還可以建立類似下圖的多級目錄的結構,第一級用來索引關鍵詞首字母,這樣可以讓我們快速的跳過無關的目錄内容,進一步提升查找的性能。

資料庫索引的作用也是類似的,本質是建立了一個資料庫表中字段的值和資料存儲位置的對應關系。同樣,為了加速查找速度,索引記錄也是按照值的順序來排列,并且有多個層級。這個資料結構一般被實作為B+樹。

淺談MySQL原理與優化(三)—— 索引

最終每一條記錄會指向資料的”存儲位置”(這個位置是廣義上的,對于不同的存儲引擎,位置的實作不同)

那麼我們怎麼樣建立資料庫索引才能産生更好的性能呢。我們注意要滿足以下的原則:

1. 索引要有區分度

好的索引是能夠把資料均勻的分成盡可能多的子群。類似于性别這樣的字段其實非常不适合做索引。因為隻能把人群分成兩部分,最多隻能過濾一半人。考慮一下省份這個字段,如果有确定的值,可以過濾掉 95%以上的人。但是省份字段并非完美,因為每個省的人數可能不一樣,有些省的人口可能人數很多,這樣的的話有些情況下可能隻能過濾掉90%的人,區分度有些損失。

2. 索引要有确定的值,NULL無法被索引

根據SQL标準,NULL值和其他值的比較是無法确定的。大部分情況下,NULL值無法被索引。即便SQL語句中用到了IS NULL的條件,也無法用到索引。是以如果字段中空值太多就不适合作為索引。如果一定要索引空值,可以考慮給空值一個特殊的确定值。但是仍然要考慮空值占比

3. 索引會影響更新,非越多越好

由于索引是根據資料字段的值進行排列的資料結構,資料值的修改會導緻索引的更新,會有一定的性能開銷,索引加的越多,性能開銷越大。

4. 多個字段可以組成複合索引,但是在MySQL中要滿足最左字首比對。

可以為多個字段建立同一個索引,索引記錄中會按照這兩個字段拼接起來排序。是以查詢要滿足最左字首比對,也就是說複合索引(a,b,c)可以對a=1 and b=2 and c =3和a=1 and b =2 和 a=1 這樣的條件生效,但是對于 b=2 and c=3,b=2 或者c=3 這類的條件無法發揮作用。

5. 避免在字段上使用子查詢

如果在字段上使用子查詢的話是無法使用索引的,比如下面這一句并不能用到actor_id這個索引。

淺談MySQL原理與優化(三)—— 索引

你也許會覺得Mysql會先執行in裡的子查詢,再使用actor_id的索引,實際上并不是這樣。Mysql會對每一個actor_id執行一遍子查詢,性能會比較差

如果将其改寫成Join則性能會提升很多。

淺談MySQL原理與優化(三)—— 索引

6. 避免在字段上使用函數

在字段上使用函數再做比較的話,是無法用到索引的,因為索引隻記錄了原始的值和資料位置的對應關系,并沒有記錄函數處理後的值。如果一定要用函數,一種處理是在資料庫中直接存儲函數處理以後的值,并建立索引。另一種辦法是使用特殊的函數索引(需要更高的mysql版本)

淺談MySQL原理與優化(三)—— 索引

希望以上的内容,對大家的日常工作能起到幫助。