hash索引基于哈希表实现,只有精确匹配索引所有列的查询才有效。Memory引擎默认使用的是此种索引。
存储引擎对所有的索隐列计算出一个哈希码,将哈希码存储在索引中,同时哈希表中保存每个数据行的指针。这样,对于此种索引查找速度是非常快的。出现哈希值碰撞的话,索引会以链表的形式存放多个记录指针到同一个哈希条目中。
举个🌰:
name | age |
---|---|
Jane | 28 |
Peter | 20 |
David | 30 |
假设使用假想的哈希函数f(),生成对应的设想值:
f('Jane') = 2323
f('Peter') = 2456
f('David') = 2400
则哈希索引的数据结构如下:
槽(slot) | 值(value) |
---|---|
2323 | 指向第1行指针 |
2400 | 指向第3行指针 |
2456 | 指向第2行指针 |
对于select * from user where `name` = 'Jane'
那么直接先算Jane
的哈希值,然后根据Jane
的hash值2323去找到对应的第一行数据,查询速度相对于B-Tree索引是要快,但是也有一些局限:
- hash索引中只有hash值和行数的指针,因此无法直接使用索引来避免读取行,但是因为这种索引读取快,性能影响不明显。
- hash索引不是按照索引值顺序存储,无法使用于排序。
- 不支持部分列匹配查找,这里面是使用索引列的全部内容来计算哈希值,例如(A,B)两列一起建索引,单纯使用A一列,那么就无法使用索引,B-Tree索引的话,因为支持匹配最左前缀,所以这种情况适用性偏好。
- 哈希索引只支持等值查询,包括=、in()、<=>,不支持where age > 10 这种范围查询。
- 哈希冲突很多的话,维护索引操作的代价也很高