B-tree索引
mysql中btree存儲的物理文件大多是balance tree(平衡樹)結構來存儲的。也就是實際存儲數據放在葉節(jié)點。而且任何一個葉節(jié)點的最短路徑都一樣。可能各種數據庫的在存放自己的btree索引時會對存儲結構做改動。例如:innodo的btree實際上是b+tree,在原有的葉節(jié)點除了存放索引等關鍵信息外,還存儲了后一個葉節(jié)點的指針信息。這是出于加快檢索多個相鄰的葉節(jié)點的效率考慮的。
主鍵索引 :
葉節(jié)點存放的,除了主鍵的數據外,還有其他字段數據的以主鍵的有序排列。所以,通過主鍵來訪問數據效率是非常高的。
btree索引:
不僅在葉節(jié)點存放索引的相關信息,也有主鍵值。
通過secondary index訪問,通過相應的索引檢索到leaf node,再通過leaf node中存放的主鍵信息來獲取數據行。
MyISAM的索引形式是b+tree,leaf node存放的是數據記錄地址。可以看的出來,myisam的索引文件僅僅保存數據記錄的地址
MyISAM索引文件和數據文件是分離的
它的主索引和輔助索引在結構上沒有區(qū)別,只是主索引要求唯一,而輔助索引可以重復。
MyISAM的索引方式也叫做“非聚集”的,之所以這么稱呼是為了與InnoDB的聚集索引區(qū)分。
MyISAM中首先按照b+tree搜索算法搜索索引,如果指定的key存在,則去除data域,再通過data域的值為地址去讀取相應的數據記錄。
InnoDB的數據文件本身就是索引文件。
InnoDB中,表數據文件本身就是按B+Tree組織的一個索引結構,這棵樹的葉節(jié)點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。
這種索引叫做聚集索引。
因為InnoDB的數據文件本身要按主鍵聚集,所以InnoDB要求表必須有主鍵(MyISAM可以沒有),如果沒有顯式指定,則MySQL系統會自動選擇一個可以唯一標識數據記錄的列作為主鍵
所以,innodb檢索直接通過主鍵非常地高效。
與MyISAM索引的不同是InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是地址。換句話說:innodb的輔助索引會引用主鍵作為自己的data域。
聚集索引這種實現方式使得按主鍵的搜索十分高效。
innodb的主鍵不宜過長,以為輔助索引會引用主索引。過長的主索引會導致輔助索引變大。
根據b+tree的特性,自增字段可以做到和b+tree的leaf node分裂順序一致。所以用自增字段做innodb的主鍵是一個很好的選擇
標準的B+tree
一個平衡的多叉樹,根節(jié)點到各葉節(jié)點的高度差不超過1,同層級節(jié)點之間有指針相互銜接。
這種數據結構,從根節(jié)點到葉節(jié)點的檢索效率相當,基于索引的順序掃描,也可以利用雙向指針快速順序移動。效率很高。
所以,B+樹索引被廣泛應用于數據庫、文件系統等場景。
順便說一下,xfs文件系統比ext3/ext4效率高很多的原因之一就是,它的文件及目錄索引結構全部采用B+樹索引,而ext3/ext4的文件目錄結構則采用Linked list, hashed B-tree、Extents/Bitmap等索引數據結構,因此在高I/O壓力下,其IOPS能力不如xfs。
哈希索引就是把鍵值通過hash算法,轉化為hash值,檢索不需要像btree那樣從根節(jié)點到葉節(jié)點這樣逐級查找。只需要一次hash算法就可定位。
Hash索引
hash索引的檢索效率高于btree,因為它是一次到位,不像btree要從根節(jié)點到枝節(jié)點,再到頁節(jié)點多次的IO訪問。
但是hash 也有很多弊端:
1.僅僅能滿足 "=","IN"和"<=>",它不能使用范圍查詢。
因為他是通過比較hash值,原先是有序的鍵值,經過hash有可能變得不連續(xù)了,so只能用于等值過濾。
2.同理,無法進行數據的排序操作,以及 like ‘xxx%’這樣的模糊查詢(模糊查詢,本質上還是范圍查詢)
3.不能利用部分索引查詢
因為它是計算組合索引合并后的hash值,而不是單獨計算。對于一個或者多個的組合索引進行查詢的時候,hash索引無法被利用。
4在任何時候都不能避免掃描全表
由于不同的hash索引存在相同的hash值,所以即使?jié)M足某個hash值的記錄條數,也無法直接在hash索引中完成查詢。還是要通過表中的數據進行實際的比較。
5.在遇到大量的重復鍵,就是hash值相等的情況下,性能不一定比btree高。
因為存在hash沖撞。
在MySQL中,只有HEAP/MEMORY引擎表才能顯式支持哈希索引(NDB也支持,但這個不常用),
InnoDB引擎的自適應哈希索引(adaptive hash index)不在此列,因為這不是創(chuàng)建索引時可指定的。
還需要注意到:HEAP/MEMORY引擎表在mysql實例重啟后,數據會丟失。
適合用hash索引
SELECT … FROM t WHERE C1 = ?; — 僅等值查詢
大多數情況下,都會有范圍查詢,模糊查詢這些,用btree索引就行。