我们常用的索引数据结构比较多的是B+TREE。
还有另一种索引数据结构是hash,但是innoDB、mysiam数据引擎不支持hash数据结构。
不同的存储引擎支持的索引类型也不一样:
InnoDB 支持事务,支持行级别锁定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;
MyISAM 不支持事务,支持表级别锁定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;
Memory 不支持事务,支持表级别锁定,支持 B-tree、Hash 等索引,不支持 Full-text 索引;
NDB 支持事务,支持行级别锁定,支持 Hash 索引,不支持 B-tree、Full-text 等索引;
Archive 不支持事务,支持表级别锁定,不支持 B-tree、Hash、Full-text 等索引;
这个玩意,mysiam和innodb是不支持的,所以,一般情况下用不上了解就好。
一:hash算法复杂度
哈希算法时间复杂度为O(1),且不只存在于索引中,每个数据库应用中都存在该数据结构。
二:HASH索引特性
在MySQL的存储引擎中,MyISAM不支持哈希索引,而InnoDB中的hash索引是存储引擎根据B-Tree索引自建的,后面会对其做具体说明。
hash索引的特点
1、 hash索引是基于hash表实现的,只有查询条件精确匹配hash索引中的所有列的时候,才能用到hash索引。
2、 对于hash索引中的所有列,存储引擎都会为每一行计算一个hash码,hash索引中存储的就是hash码。
3、 hash索引包括键值、hash码和指针 。
因为hash索引本身只需要存储对应的hash值,所以索引的结构十分紧凑,这也让hash索引查找的速度非常快。然而,hash索引也是存在其限制的:
三:hash索引的限制
1、 Hash索引必须进行二次查找
使用哈市索引两次查找,第一次找到相应的行,第二次读取数据,但是被频繁访问到的行一般会缓存在内存中,这点对数据库性能的影响不大。
2、hash索引不能用于外排序
hash索引存储的是hash码而不是键值,所以无法用于外排序
3、hash索引不支持部分索引查找也不支持范围查找
只能用到等值查询,不能范围和模糊查询
4、hash索引中的hash码的计算可能存在hash冲突
当出现hash冲突的时候,存储引擎必须遍历整个链表中的所有行指针,逐行比较,直到找到所有的符合条件的行,若hash冲突很多的话,一些索引的维护代价机会很高,所以说hash索引不适用于选择性很差的列上(重复值很多)。姓名、性别、身份证(合适)
上面说到InnoDB的“自适应hash索引”。就是当InnoDB注意到某些索引值被使用的非常频繁时,它会在内存中基于B-Tree索引上在创建一个hash索引,这样就让B-tree索引也具有hash索引的一些优点。这是一个完全自动的内部的行为,用户无法控制或配置,不过,如果有需要,完全可以关闭该功能。
四:创建自定义hash索引
若存储引擎不支持hash索引,又想拥有hash索引所带来的性能提升,则可以模拟InnoDB一样创建哈希索引。
思路也比较简单,就是在B-tree基础上创建一个伪哈希索引。这和真正的hash索引不是一回事,因为还是采用B-Tree进行查找,但是它使用的是hash值而不是键本身进行查找。只需要在查询的where子句中手动指定使用hash函数即可。下面举个简单的例子:
比如:当我们需要存储大量的URL,并需要根据URL进行搜索查找。若用B-Tree来存储URL,存储的内容就会很大。此时的查询语句就是:
select id from url where url = "www.baidu.com";
若删除原来的url列上的索引,而新增一个被索引的url_crc列,使用crc32做hash函数,则可以使用如下方式查询:
select id from url where url = "www.baidu.com" and url_crc=CRC32("www.baidu.com");
这样做的话,性能就会有很大提升,因为mysql优化器会使用这个选择性高而体积很小的基于url_crc列的多音来完成查找。即使有多个记录相同的索引值,查找仍然很快,只需要根据hash值做快速的整数比较就能找到索引条目,然后一一返回对应的行。
五:Hash缺点
1、需要维护hash值,可以手动维护,也可以使用触发器实现。2、若数据表非常大的话,CRC32()会出现大量hash冲突,则可以自己实现一个64位的hash函数,这个自定义的hash函数要返回整数而不是字符串,因为范围整数,对此效率更高。一个简单的办法就是使用MD5()函数返回值的一部分来作为自定义的hash函数。但是这可能比自己写一个hash算法性能要差一些。
以上大概就是hash索引的基本内容。
再说一次,这个玩意他不支持mysiam和innodb,所以,可能是用的不多。