按數據結構分類可分爲:B+tree索引、Hash索引、Full-text索引。
按物理存儲分類可分爲:聚簇索引、二級索引(輔助索引)。
按字段特性分類可分爲:主鍵索引、普通索引、前綴索引。
按字段個數分類可分爲:單列索引、聯合索引(複合索引、組合索引)。算法
MySQL索引按數據結構分類可分爲:B+tree索引、Hash索引、Full-text索引。數據庫
- | InnoDB | MyISAM | Memory |
---|---|---|---|
B+tree索引 | √ | √ | √ |
Hash索引 | × | × | √ |
Full-text索引 | √(MySQL5.6+) | √ | × |
注:InnoDB實際上也支持Hash索引,可是InnoDB中Hash索引的建立由存儲引擎引擎自動優化建立,不能人爲干預是否爲表建立Hash索引
B+tree 是MySQL中被存儲引擎採用最多的索引類型。B+tree 中的 B
表明平衡(balance),而不是二叉(binary),由於 B+tree 是從最先的平衡二叉樹演化而來的。下面展現B+tree數據結構與其餘數據結構的對比。安全
B-tree 中的每一個節點根據實際狀況能夠包含多條數據信息和子節點,以下圖所示爲一個3階的B-tree:網絡
(圖片來源於網絡)數據結構
相對於B-tree,B+tree有如下兩點不一樣:函數
(圖片來源於網絡)性能
(圖片來源於網絡)優化
紅黑樹是一種弱平衡二叉查找樹。經過對任何一條從根到葉子的路徑上各個節點着色的方式的限制,紅黑樹確保沒有一條路徑會比其餘路徑長出兩倍。spa
對於有N個葉子結點的 B+tree,其搜索複雜度爲 O(logdN)
,其中 d(degree) 爲 B+tree 的度,表示節點容許的最大子節點個數爲d個,在實際應用當中,d值通常是大於100的,即便數據量達到千萬級別時B+tree的高度依然維持在3-4左右,保證了3-4次磁盤I/O操做就能查詢到目標數據。3d
紅黑樹是二叉樹,節點子節點個數爲兩個,意味着其搜索複雜度爲 O(logN)
,樹的高度也會比 B+tree 高出很多,所以紅黑樹檢索到目標數據所需經歷的磁盤I/O次數更多。
Hash 索引結構的特殊性,其檢索效率很是高,索引的檢索能夠一次定位,不像B-Tree 索引須要從根節點到枝節點,最後才能訪問到頁節點這樣屢次的IO訪問,因此 Hash 索引的查詢效率要遠高於 B-Tree 索引。雖然 Hash 索引效率高,可是 Hash 索引自己因爲其特殊性也帶來了不少限制和弊端,主要有如下這些。
=
, IN
和 <=>
(表示NULL安全的等價) 查詢,不能使用範圍查詢。因爲 Hash 索引比較的是進行 Hash 運算以後的 Hash值,因此它只能用於等值的過濾,不能用於基於範圍的過濾,由於通過相應的 Hash算法處理以後的 Hash 值的大小關係,並不能保證和Hash運算前徹底同樣。
因爲 Hash 索引中存放的是通過 Hash 計算以後的 Hash值,並且Hash值的大小關係並不必定和 Hash運算前的鍵值徹底同樣,因此數據庫沒法利用索引的數據來避免任何排序運算;
對於組合索引,Hash 索引在計算 Hash 值的時候是組合索引鍵合併後再一塊兒計算 Hash 值,而不是單獨計算 Hash值,因此經過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash 索引也沒法被利用。
Hash 索引是將索引鍵經過 Hash 運算以後,將 Hash運算結果的 Hash值和所對應的行指針信息存放於一個 Hash 表中,因爲不一樣索引鍵可能存在相同 Hash 值,因此即便取知足某個 Hash 鍵值的數據的記錄條數,也沒法從 Hash索引中直接完成查詢,仍是要經過訪問表中的實際數據進行相應的比較,並獲得相應的結果。
選擇性比較低的索引鍵,若是建立 Hash 索引,那麼將會存在大量記錄指針信息存於同一個Hash值相關聯。這樣要定位某一條記錄時就會很是麻煩,會浪費屢次表數據的訪問,而形成總體性能低下
因爲範圍查詢是MySQL數據庫查詢中常見的場景,Hash表不適合作範圍查詢,它更適合作等值查詢。另外Hash表還存在Hash函數選擇和Hash值衝突等問題。所以,B+tree索引要比Hash表索引有更廣的適用場景。
MySQL索引按葉子節點存儲的是否爲完整表數據分爲:聚簇索引、二級索引(輔助索引)。全表數據存儲在聚簇索引中,聚簇索引之外的其餘索引叫作二級索引,也叫輔助索引。
聚簇索引的每一個葉子節點存儲了一行完整的表數據,葉子節點間按id列遞增鏈接,能夠方便地進行順序檢索。
InnoDB表要求必須有聚簇索引,默認在主鍵字段上創建聚簇索引,在沒有主鍵字段的狀況下,表的第一個非空的惟一索引將被創建爲聚簇索引,在前二者都沒有的狀況下,InnoDB將自動生成一個隱式的自增id列,並在此列上創建聚簇索引。
MyISAM表中的主鍵索引和非主鍵索引的結構是同樣的,索引的葉子節點不存儲表數據,存放的是表數據的地址。因此,MyISAM表能夠沒有主鍵。
MyISAM表的數據和索引是分開存儲的。MyISAM表的主鍵索引和非主鍵索引的區別僅在於主鍵索引的B+tree上的key必須符合主鍵的限制,非主鍵索引B+tree上的key只要符合相應字段的特性就能夠了。
二級索引的葉子節點並不存儲一行完整的表數據,而是存儲了聚簇索引所在列的值。
因爲二級索引的葉子節點不存儲完整的表數據,索引當經過二級索引查詢到聚簇索引列值後,還須要回到聚簇索引也就是表數據自己進一步獲取數據。
回表查詢 須要額外的 B+tree 搜索過程,必然增大查詢耗時。
須要注意的是,經過二級索引查詢時,回表不是必須的過程,當SELECT的全部字段在單個二級索引中都可以找到時,就不須要回表,MySQL稱此時的二級索引爲覆蓋索引或觸發了索引覆蓋。
能夠用Explain命令查看SQL語句的執行計劃,執行計劃的Extra字段中若出現Using index,表示查詢觸發了索引覆蓋。
MySQL索引按字段特性分類可分爲:主鍵索引、普通索引、前綴索引。
創建在主鍵上的索引被稱爲主鍵索引,一張數據表只能有一個主鍵索引,索引列值不容許有空值,一般在建立表時一塊兒建立。
創建在UNIQUE字段上的索引被稱爲惟一索引,一張表能夠有多個惟一索引,索引列值容許爲空,列值中出現多個空值不會發生重複衝突。
創建在普通字段上的索引被稱爲普通索引。
前綴索引是指對字符類型字段的前幾個字符或對二進制類型字段的前幾個bytes創建的索引,而不是在整個字段上建索引。前綴索引能夠創建在類型爲char、varchar、binary、varbinary的列上,能夠大大減小索引佔用的存儲空間,也能提高索引的查詢效率。
MySQL索引按字段個數分類可分爲:單列索引、聯合索引(複合索引、組合索引)。
創建在單個列上的索引被稱爲單列索引。
創建在多個列上的索引被稱爲聯合索引,又叫複合索引、組合索引。