哈希索引基于哈希表实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码,哈希码是一个较小的值,并且不同键值计算出来的哈希码也不同。哈希索引将所有哈希码存放在索引中,同时在哈希表存放指向数据行的指针。
在哈希索引中,采用桶(bucket)来表示一条或多条记录的存储单元。令K表示搜索码的集合,B表示所有桶地址的集合。哈希函数h是一个从K中的找出B中的一个桶地址。
插入一条搜索码为的数据行,计算,得出一个哈希码,该哈希码能够索引到能够存放该数据行的桶的地址,如果桶不满。
搜索一条搜索码为的数据行,计算,得出一个哈希码,该哈希码能够索引该数据行所存放桶的地址。如果有两个搜索码和,它们计算的哈希码一致,如果该哈希码索引的桶能够存放这两个数据行,则在索引到的桶中查找和 。
在MySQL中,只有Memory引擎显示支持哈希索引,这也是Memory引擎搜索表的默认索引类型。
有如下表:
CREATE DATABASE Student;
CREATE TABLE Student
(
id int NOT NULL ,
name char(10) NOT NULL ,
score float(1) NULL ,
KEY USING HASH(id)
)ENGINE=MEMORY;
INSERT INTO Student
(
id,name,score
)
VALUES
( 78, 'Crick',97.6 ),
( 125,'Katz', 85.3 ),
( 634,'Gold', 66.6 );
+-----+-------+-------+
| id | name | score |
+-----+-------+-------+
| 78 | Crick | 97.6 |
| 125 | Katz | 85.3 |
| 634 | Gold | 66.6 |
+-----+-------+-------+
主键id采用哈希索引的方式,因此假设进行对id计算后得到的hash code如下:
h(78)= 0;
h(125) = 2;
h(634) = 1;
采用哈希表的方式进行存储
如果此时插入一行且该主键的计算出的哈希码的值与前面的某行计算出的哈希
码一致,会产生哈希冲突。例如:
h(35) = 2
查询id=35的数据行,计算35的哈希码,根据哈希码索引出该数据行的指针,但是该哈希码对应的两个按照链式存储的数据行指针,还需要在该链上进行查找。
也可以采用桶进行存储,假设每个桶能存储三个数据行的指针,如果每个数据行的主键计算所得哈希码相同,存放在一个桶中。如果发生桶溢出,则会在该桶后面以链式进行链接一个溢出桶。溢出桶大小与刚才的桶一致。
哈希索引并不是按照索引值索引值顺序存储,所以也就无法用于排序。
哈希索引也不支持部分索引列匹配查找,因为哈希索引始终使用索引列的全部内容来计算哈希值的。
哈希索引只支持等值比较查询,包括=,IN,<=>,也不支持范围查询。
当出现哈希冲突时,存储引擎必须遍历链表所有数据行指针,逐行比较,直到找出符合条件的数据行。
如果哈希冲突很多,一些索引维护操作代价也很高。