一、哈希索引
思维导图
1.哈希索引的特点
- 基于哈希表的实现,只有精确匹配索引所有列的查询才有效
- 在mysql中,只有memory的存储引擎显式支持哈希索引
- 哈希索引自身只需存储对应的hash值,所以索引的结构十分紧凑,这让哈希索引查找的速度非常快
2.哈希索引的限制
- 1、哈希索引只包含哈希值和行指针,而不存储字段值,索引不能使用索引中的值来避免读取行
- 2、哈希索引数据并不是按照索引值顺序存储的,所以无法进行排序
- 3、哈希索引不支持部分列匹配查找,哈希索引是使用索引列的全部内容来计算哈希值
- 4、哈希索引支持等值比较查询,也不支持任何范围查询
- 5、访问哈希索引的数据非常快,除非有很多哈希冲突,当出现哈希冲突的时候,存储引擎必须遍历链表中的所有行指针,逐行进行比较,直到找到所有符合条件的行
思考:什么是哈希冲突?
因为哈希值是通过一定算法生成的,那么就有一定的可能出现不同的输入得到的Hash值是一样的,就算我们可以通过调整算法尽量减少这种情况,但是也不可完全避免。发生这种情况后,我们就会出现两个不同的键值被映射到同一个位置了,这就是哈希冲突。
思考:哈希冲突怎样解决?
1.开放地址法:
基本思想:当发生地址冲突的时候,按照某种方法继续探测哈希表中的其他存储单元,直到找到空位置为止;
所用公式 Hi(key) = [H(key) + di]mod m;其中i = 1、2、3…k(k<m-1),H(key)为关键字key的直接hash地址;M为hash表的长度;
di为再次探测时的地址增量;根据di的不同取法,有不同的称呼;
线性探测再散列:di = 1、2、3、4…k (k<m-1)
二次探测再散列:di = 12,-12,22,-22…k2,-k2 (k<=m/2)
伪随机再散列:di = 伪随机数
2.再hash的方法:
当发生冲突时,使用第二个、第三个、哈希函数计算地址,直到无冲突时。缺点:计算时间增加。 比如上面第一次按照姓首字母进行哈希,如果产生冲突可以按照姓字母首字母第二位进行哈希,再冲突,第三位,直到不冲突为止;
3.拉链法:
在HashMap中 就是使用拉链法 来解决hash冲突的问题的;将所有关键字为同义词的记录存储在同一线性链表中。
4.建立公共溢出区:
建立公共溢出区的基本思想是:假设哈希函数的值域是[1,m-1],则设向量HashTable[0…m-1]为基本表,每个分量存放一个记录,另外设向量OverTable[0…v]为溢出表,所有关键字和基本表中关键字为同义词的记录,不管它们由哈希函数得到的哈希地址是什么,一旦发生冲突,都填入溢出表。
思考:HashMap处理哈希冲突采用的是哪种方式?
HashMap解决哈希冲突采用的是链地址法。属于开散列。说白了就是把冲突的key连接起来,放到桶里。当桶中的元素个数不超过6个时,以单链表的形式串起来,当桶中的元素个数超过6个时,以红黑树的形式串起来。
- 6、哈希冲突比较多的话,维护的代价也会很高
3.案例
当需要存储大量的URL,并且根据URL进行搜索查找,如果使用B+树,存储的内容就会很大
select id from url where url=""
也可以利用将url使用CRC32做哈希,可以使用以下查询方式:
select id fom url where url="" and url_crc=CRC32("")
此查询性能较高原因是使用体积很小的索引来完成查找