MySQL 哈希索引

哈希索引基於哈希表實現,只有精確匹配索引全部列的查詢纔有效。mysql

在MySQL中只有Memory引擎顯示支持哈希索引,也是memory引擎表的默認索引類型。memory引擎是支持非惟一哈希索引的。若是多個列的哈希值相同,索引會以鏈表 的方式存放多個記錄指針道同一個哈希條目中。sql

舉個粒子:數據庫

create table testhash(
fname varchar(50) not null,
lname varchar(50) not null,
key using hash(fname)
)engine=memory;


數據庫中的數據:
mysql> select * from testhash;
+--------+-----------+
| fname  | lname     |
+--------+-----------+
| Baron  | Schwartz  |
| Arjen  | Lentz     |
| Peter  | Zaitsev   |
| Vadim  | Tkachenko |
+--------+-----------+
4 rows in set (0.00 sec)

假設f() 爲哈希函數,f(fname) 的返回值是其哈希值,對應槽位。槽位是按順序排列的。每一個槽位上的值指向數據。
(結構能夠理解爲 jdk 1.7 中的hashmap的數據結構,一個數組和鏈表的形式)
image.png數組

ERROR 1054 (42S22): Unknown column 'lane' in 'field list'
mysql> select lname from testhash where fname ='Peter';
+---------+
| lname   |
+---------+
| Zaitsev |
+---------+
1 row in set (0.00 sec)

查找的過程是是先計算'Peter'的哈希值,並使用改值尋找對應的記錄指針,也就是計算f('Peter'),獲得其哈希值爲 3468 ,而後在對應的槽位上找到記錄指針,找到對應行上的數據,最後一步是比較查找的值是否爲'Peter' ,以確保就是要查找的行。數據結構

哈希索引的限制函數

  • 哈希索引值包含哈希值和行指針,而不存儲字段值,因此不能使用索引中的值來避免讀取行。
  • 哈希索引數據並非按照索引值順序存儲的,因此沒法用於排序
  • 哈希索引也不支持部分索引匹配查找,由於哈希索引始終是使用索引列的所有內容來計算哈希值。例如,在數據列(A,B)上簡歷哈希索引,若是查詢只有數據列A,則沒法使用該索引。
  • 哈希索引只支持等值比較查詢,包括 =、IN() 、<=> ,也不支持任何範圍查找,例如 where price > 100.
  • 訪問哈希索引的數據很是快,除非歐不少哈希衝突。當出現哈希衝突的時候,存儲引擎必須遍歷鏈表中的行指針,裝進行比較,直到找到全部符合條件的行。
  • 若是哈希衝突不少的時候,一些索引維護操做的代價也會很是高。例如,若是在某個選擇性很低(哈希衝突不少)的列上創建哈西索引,那麼當從表中刪除一行時,存儲引擎須要遍歷對應哈希值的鏈表中的每一行,找到並刪除對應行的引用,衝突越多,代價越大。

InnoDB引擎有一個特殊的功能叫作"自適應哈希索引。當InnoDB注意到某些索引值被引用得很是頻繁時,他會在內存中基於B-Tree索引智商在建立一個哈希索引,這樣就讓B-Tree索引也具備哈希索引的一些優勢。這是一個徹底自動 的、內部的行爲,用戶沒法控制或配置。不過若是有必要,徹底能夠關閉該功能。spa

相關文章
相關標籤/搜索