Hash索引原理:
hash索引是将索引键通过hash运算后,将运算结果的hash值和对应的行指针信息存储Bucket。
引用:‘’哈希索引(hash index)基于哈希表实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码(hash code),哈希码是一个较小的值,并且不同键值的行计算出来的哈希码也不一样。哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。对于hash相同的,采用链表的方式解决冲突。类似于hashmap。因为索引的结构是十分紧凑的,所以hash索引的查询很快‘’
keys------->Buckets--------->entries加载进入内存
相比与B+树,hash索引可以直接key值查询出相应的Buckets信息(进行哈希算法计算,得到哈希值,排序在哈希数组上。所以Hash索引可以一次定位,其效率很高),不用像b+树从根节点遍历到叶节点,减少了很多磁盘I/O.
Hash索引的缺陷:
1.仅满足‘=’和‘in’,不可以做范围查询(哈希索引只支持等值比较查询,包括=、IN()、<>(注意<>和<=>是不同的操作)。也不支持任何范围查询,例如WHERE price>100。)
hash索引因为底层是哈希表,数据存储在哈希表中顺序是没有关联的,所以他不适合范围查找,如果要范围查找就需要全表扫描,他只适合全值扫描
因为索引值需要进行hash运算将值和行指针信息->Bucket,所以查询还是相当于从Bucket查询。
2.哈希索引数据并不是按照索引值顺序存储的,所以也就无法用于排序。
由于Hash索引中存放的是经过 Hash 计算之后的 Hash 值,而且Hash值的大小关系并不一定和 Hash 运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算;
3.哈希索引也不支持部分索引列匹配查找,因为哈希索引始终是使用索引列的全部内容来计算哈希值的。
4.哈希索引只包含哈希值和行指针,而不存储字段值,所以不能使用索引中的值来避免读取行。
5.
当哈希值大量重复且数据量非常大时,其检索效率并没有Btree索引高的。访问哈希索引的数据非常快,除非有很多哈希冲突(不同的索引列值却有相同的哈希值)。当出现哈希冲突的时候,存储引擎必须遍历链表中所有的行指针,逐行进行比较,直到找到所有符合条件的行。
如果哈希冲突很多的话,一些索引维护操作的代价也会很高。例如,如果在某个选择性很低(哈希冲突很多)的列上建立哈希索引,那么当从表中删除一行时,存储引擎需要遍历对应哈希值的链表中的每一行,找到并删除对应行的引用,冲突越多,代价越大
6.Hash索引在任何时候都不能避免表扫描
Hash 索引是将索引键通过 Hash 运算之后,将 Hash运算结果的 Hash 值和所对应的行指针信息存放于一个 Hash 表中,由于不同索引键存在相同 Hash 值,所以即使取满足某个 Hash 键值的数据的记录条数,也无法从 Hash 索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果。