mysql hash索引和B+tree索引的區別

在MySQL中Innodb和myisam的默認索引都是B+TREE,

B+TREE索引

B+Tree索引是mysql中最常見的索引算法,因爲他不僅僅可以被用在=,>,>=,<,<=和between這些操作符。而且還可以用戶like操作符,只要操作符不是一個通配符開始的常量都可以使用索引,例如:

select * from user where name like ‘jack%’; 
select * from user where name like ‘jac%k%’; 

hash

Hash索引只能對於對等比較,例如=,<=>,操作符。由於是一次性定位,不像BTree索引需要從根節點到枝節點,最後才能訪問到葉子節點這麼多次IO訪問,所以檢索效率遠高於BTree.

  1. Hash索引僅僅能滿足“=”,“IN”,“<=>”查詢,不能使用範圍查詢。
  2. 聯合索引中,Hash索引不能利用部分索引鍵查詢。
    對於聯合索引中的多個列,Hash是要麼全部使用,要麼全部不使用,並不支持BTree支持的聯合索引的最優前綴,也就是聯合索引的前面一個或幾個索引鍵進行查詢時,Hash索引無法被利用。
  3. Hash索引無法避免數據的排序操作
    由於Hash索引中存放的是經過Hash計算之後的Hash值,而且Hash值的大小關係並不一定和Hash運算前的鍵值完全一樣,所以數據庫無法利用索引的數據來避免任何排序運算。
  4. Hash索引任何時候都不能避免表掃描
    Hash索引是將索引鍵通過Hash運算之後,將Hash運算結果的Hash值和所對應的行指針信息存放於一個Hash表中,由於不同索引鍵存在相同Hash值,所以即使滿足某個Hash鍵值的數據的記錄條數,也無法從Hash索引中直接完成查詢,還是要通過訪問表中的實際數據進行比較,並得到相應的結果。
  5. Hash索引遇到大量Hash值相等的情況後性能並不一定會比BTree高
    對於選擇性比較低的索引鍵,如果創建Hash索引,那麼將會存在大量記錄指針信息存於同一個Hash值相關聯。這樣要定位某一條記錄時就會非常麻煩,會浪費多次表數據訪問,而造成整體性能底下。

Hash索引

所謂Hash索引,當我們要給某張表某列增加索引時,將這張表的這一列進行哈希算法計算,得到哈希值,排序在哈希數組上。所以Hash索引可以一次定位,其效率很高,而Btree索引需要經過多次的磁盤IO,但是innodb和myisam之所以沒有采用它,是因爲它存在着好多缺點:

1、因爲Hash索引比較的是經過Hash計算的值,所以只能進行等式比較,不能用於範圍查詢

1、每次都要全表掃描

2、由於哈希值是按照順序排列的,但是哈希值映射的真正數據在哈希表中就不一定按照順序排列,所以無法利用Hash索引來加速任何排序操作

3、不能用部分索引鍵來搜索,因爲組合索引在計算哈希值的時候是一起計算的。

4、當哈希值大量重複且數據量非常大時,其檢索效率並沒有Btree索引高的。

Btree索引

至於Btree索引,它是以B+樹爲存儲結構實現的。

但是Btree索引的存儲結構在Innodb和MyISAM中有很大區別。

在MyISAM中,我們如果要對某張表的某列建立Btree索引的話,如圖:

所以我們經常會說MyISAM中數據文件和索引文件是分開的。

因此MyISAM的索引方式也稱爲非聚集,Innodb的索引方式成爲聚集索引。

至於輔助索引,類似於主索引,唯一區別就是主索引上的值不能重複,而輔助索引可以重複。

因此當我們根據Btree索引去搜索的時候,若key存在,在data域找到其地址,然後根據地址去表中查找數據記錄。

至於Innodb它跟上面又有很大不同,它的葉子節點存儲的並不是表的地址,而是數據

我們可以看到這裏並沒有將地址放入葉子節點,而是直接放入了對應的數據,這也就是我們平常說到的,Innodb的索引文件就是數據文件,

那麼對於Innodb的輔助索引結構跟主索引也相差很多,如圖:

我們可以發現,這裏葉子節點存儲的是主鍵的信息,所以我們在利用輔助索引的時候,檢索到主鍵信息,然後再通過主鍵去主索引中定位表中的數據,這就可以說明Innodb中主鍵之所以不宜用過長的字段,由於所有的輔助索引都包含主索引,所以很容易讓輔助索引變得龐大。

我們還可以發現:在Innodb中儘量使用自增的主鍵,這樣每次增加數據時只需要在後面添加即可,非單調的主鍵在插入時會需要維持B+tree特性而進行分裂調整,十分低效。

Btree索引中的最左匹配原則:
Btree是按照從左到右的順序來建立搜索樹的。比如索引是(name,age,sex),會先檢查name字段,如果name字段相同再去檢查後兩個字段。

所以當傳進來的是後兩個字段的數據(age,sex),因爲建立搜索樹的時候是按照第一個字段建立的,所以必須根據name字段才能知道下一個字段去哪裏查詢。

所以傳進來的是(name,sex)時,首先會根據name指定搜索方向,但是第二個字段缺失,所以將name字段正確的都找到後,然後纔會去匹配sex的數據。

建立索引的規則:
1、利用最左前綴:Mysql會一直向右查找直到遇到範圍操作(>,<,like、between)就停止匹配。比如a=1 and b=2 and c>3 and d=6;此時如果建立了(a,b,c,d)索引,那麼後面的d索引是完全沒有用到,當換成了(a,b,d,c)就可以用到。

2、不能過度索引:在修改表內容的時候,索引必須更新或者重構,所以索引過多時,會消耗更多的時間。

3、儘量擴展索引而不要新建索引

4、最適合的索引的列是出現在where子句中的列或連接子句中指定的列。

5、不同值較少的列不必要建立索引(性別)。

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