索引的原理:Hash索引的底层原理是什么?

1,112 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情

前言

我们常用的索引数据结构比较多的是B+TREE。还有另一种索引数据结构Hash索引经常遇到,这次来介绍下HASH索引的原理和使用。了解索引的结构及原理可以帮助我们更好的使用索引,避免盲目使用索引带来的不必要的麻烦,关于B+树的原理可以看上一篇文章juejin.cn/post/715948…,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

什么是Hash索引

哈希索引是基于哈希表实现,哈希表是一种key-value的数据结构,能够通过key以近乎O(1)的时间复杂度获取到value的值,因此,对于等值查询(=,in)的性能非常高。下面我们通过示例具体看一下:

使用B+Tree索引:

使用Hash索引:

通过上面运行结果比较可以看到,采用Hash索引的方式比B+Tree索引快了2毫秒的时间,检索效率提升的非常明显。下面我们来看下Hash索引是怎么实现的?

Hash实现方式

Hash表是一种线性数据结构,这种数据结构的底层一般是通过数组来实现的,在进行数据增删改查的时候,Hash表首先通过Hash函数对某个键值进行Hash操作,这个Hash操作会将这个键值映射到数组的某个下标,获得下标以后就可以直接对数组中的数据进行操作了。

Hash函数

Hash函数又称散列函数,就是把任意长度的输入,通过散列算法,变换成固定长度的散列值。

常用Hash函数有:

  1. 直接寻址法。取关键字或关键字的某个线性函数值为散列地址。即H(key)=key或H(key) = a·key + b,其中a和b为常数(这种散列函数叫做自身函数)
  2. 数字分析法。分析一组数据,比如一组员工的出生年月日,这时我们发现出生年月日的前几位数字大体相同。
  3. 平方取中法。取关键字平方后的中间几位作为散列地址。
  4. 折叠法。将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后取这几部分的叠加和(去除进位)作为散列地址。

哈希冲突

对于不同的输入值,Hash函数可能会给出相同的输出,这种情况就叫做Hash冲突。

示例:

哈希冲突是不可避免的,我们常用解决哈希冲突的方法有开放地址法拉链法

Hash和B+ 树索引区别

  • Hash 索引不能进行范围查询,而 B+ 树可以。这是因为 Hash 索引指向的数据是无序的,而 B+ 树的叶子节点是个有序的链表。
  • Hash 索引不支持联合索引的最左侧原则(即联合索引的部分索引无法使用),而 B+ 树可以。对于联合索引来说,Hash 索引在计算 Hash 值的时候是将索引键合并后再一起计算 Hash 值,所以不会针对每个索引单独计算 Hash 值。因此如果用到联合索引的一个或者几个索引时,联合索引无法被利用。
  • Hash 索引不支持 ORDER BY 排序,因为 Hash 索引指向的数据是无序的,因此无法起到排序优化的作用,而 B+ 树索引数据是有序的,可以起到对该字段 ORDER BY 排序优化的作用。同理,我们也无法用 Hash 索引进行模糊查询,而 B+ 树使用 LIKE 进行模糊查询的时候,LIKE 后面前模糊查询(比如 % 开头)的话就可以起到优化作用。

总结

以上大概就是hash索引的基本内容。

哈希索引是基于哈希表实现,哈希表是一种key-value的数据结构,是通过hash函数将key变换成固定长度的散列值。

对于不同的输入值,Hash函数可能会给出相同的输出,这种情况就叫做Hash冲突。

因为 Hash 索引指向的数据是无序的,所以Hash 索引不能进行范围查询,也不支持 ORDER BY 排序。因为这些限制,哈希索引只适用于某些特定的场合。