索引基礎
索引是存儲引擎用于快速找到記錄的一種數據結構。索引能輕易將查詢性能提高幾個數量級疙赠。索引可以包含一個或多個列的值付材。如果索引包含多個列,那么列的順序也十分重要圃阳,因為 MySQL 只能高效地使用索引的最左前綴列厌衔。
索引的類型
- B-TREE 索引:使用 B-Tree 數據結構。大多數 MySQL 引擎都支持這種索引捍岳。不過底層的存儲引擎也可能使用不同的存儲結構富寿。InnoDB 使用的是B+Tree。B-Tree 索引適用于**全鍵值锣夹、鍵值范圍或鍵前綴查找(最左前綴)页徐。B-TREE 索引的一些限制:1.如果不是按照索引的最左列開始查找,則無法使用索引银萍。2.不能跳過索引中的列变勇。3.如果查詢中有某個列的范圍查詢,則其右邊所有列都無法使用索引優(yōu)化查找贴唇。
- 哈希索引:基于哈希表實現搀绣,只有精確匹配索引所有列的查詢才有效。只有Memory引擎顯式支持哈希索引戳气。
索引的優(yōu)點
- 索引大大減少了服務器需要掃描的數據量链患。
- 索引可以幫助服務器避免排序和臨時表。
- 索引可以將隨機 I/O 變?yōu)轫樞?I/O瓶您。
高性能的索引策略
獨立的列
索引列不能是表達式的一部分麻捻,也不能是函數的參數纲仍。
前綴索引和索引選擇性
有時候需要索引很長的字符列,這會讓索引變得大且慢贸毕。這種情況下可以索引開始的部分字符巷折,這樣可以大大節(jié)約索引空間,從而提高索引效率崖咨。但這樣也會降低索引的選擇性锻拘。索引的選擇性是指,不重復的索引值和數據表的記錄總數的比值击蹲。索引的選擇性越高則查詢效率越高署拟,因為選擇性高的索引可以讓 MySQL 在查找時過濾掉更多的行。
前綴索引是一種能使索引更小歌豺、更快的有效辦法推穷,但也有缺點:MySQL 無法使用前綴索引做 ORDER BY 和 GROUP BY,也無法使用前綴索引做覆蓋掃描类咧。
多列索引
在多個列上建立獨立的單列索引大部分情況下并不能提高 MySQL 的查詢性能馒铃。索引合并策略(index merge),在一定程度上可以使用表上的多個單列索引來定位指定的行痕惋,但更多時候說明來表上的索引建的很糟糕区宇。
選擇合適的索引列順序
正確的順序依賴于使用該索引的查詢,并且同時需要考慮如何更好地滿足排序和分組的需要值戳。
聚簇索引
聚簇索引不是一種單獨的索引類型议谷,而是一種數據存儲方式。InnoDB的聚簇索引實際上在同一個結構中保存了 B-Tree 索引和數據行堕虹。數據行實際上存放在索引的葉子節(jié)點中卧晓。因為無法同時把數據行放在兩個不同的地方,所以一個表只能有一個聚簇索引(覆蓋索引可以模擬多個聚簇索引的情況)赴捞。InnoDB通過主鍵聚集數據逼裆,如果沒有主鍵,InnoDB會選擇一個唯一的非空索引代替赦政。如果沒有這樣的索引胜宇,則隱式定義一個主鍵來作為聚簇索引。
聚簇索引優(yōu)點:
- 可以把相關數據保存在一起昼钻,減少磁盤I/O掸屡。
- 數據訪問更快。
- 使用覆蓋索引掃描的查詢可以直接使用頁節(jié)點的主鍵值然评。
聚簇索引缺點:
- 如果數據全部放在內存中,則聚簇索引沒什么優(yōu)勢來狈究。
- 插入速度嚴重依賴于插入順序碗淌。按照主鍵的順序插入是速度最快的方式盏求。
- 更新聚簇索引的代價很高。
- 在插入新行或主鍵被更新導致需要移動行的時候亿眠,可能面臨頁分裂的問題碎罚。
- 可能導致全表掃描變慢,尤其是行比較稀疏纳像,或者由于頁分裂導致數據存儲不連續(xù)荆烈。
- 二級索引占用了更多空間,因為二級索引的葉子節(jié)點包含了引用行的主鍵竟趾。
- 二級索引訪問需要兩次索引查找憔购。
覆蓋索引
如果一個索引包含(或者說覆蓋)所有需要查詢的字段的值,我們就稱之為“覆蓋索引”岔帽。
覆蓋索引的好處:
- 索引條目通常遠小于數據行大小
- 簡單的范圍查詢能使用完全順序的索引訪問玫鸟。
- InnoDB的二級索引如果能夠覆蓋查詢,則可以避免對主鍵索引的二次查詢犀勒。
使用索引掃描做排序
MySQL 有兩種方式可以生成有序的結果:通過排序操作或者按索引順序掃描屎飘。只有當索引的列順序和 ORDER BY 字句的順序完全一致,并且所有列的排序方向都一樣時贾费,MySQL 才能夠使用索引來對結果做排序钦购。如果查詢需要關聯多張表,則只有當 ORDER BY 字句引用的字段全部為第一個表時褂萧,才能使用索引做排序肮雨。
索引和鎖
索引可以讓查詢鎖定更少的行。InnoDB 只有在訪問行的時候才會對其加鎖箱玷,而索引能夠減少InnoDB訪問的行數怨规,從而減少鎖的數量。但這只有當 InnoDB 在存儲引擎層能夠過濾掉所有不需要的行時才有效锡足。