索引的分类--B-Tree索引和Hash索引
Posted 依米熊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了索引的分类--B-Tree索引和Hash索引相关的知识,希望对你有一定的参考价值。
索引是存储引擎用来快速查找记录的一种数据结构,按照实现的方式有不同的种类,想B-Tree索引,hash索引,空间数据索引和全文索引等。下面主要说一下B-Tree索引和Hash索引。
人们在谈论索引的时候如果没有特别说明,一般指的是B-Tree索引。B-Tree索引是使用B-Tree数据结构来存储索引的。B-Tree通常意味着所有的值是按照顺序存储的。B-Tree树有如下几个特征:
⑴树中每个结点至多有m 棵子树;
⑵若根结点不是叶子结点,则至少有两棵子树;
⑶除根结点之外的所有非终端结点至少有[m/2] 棵子树;
⑷所有的非终端结点中包含以下信息数据:
(n,A0,K1,A1,K2,…,Kn,An)
其中:Ki(i=1,2,…,n)为关键码,且Ki<Ki+1,
Ai 为指向子树根结点的指针(i=0,1,…,n),且指针Ai-1 所指子树中所有结点的关键码均小于Ki (i=1,2,…,n),An 所指子树中所有结点的关键码均大于Kn.
n 为关键码的个数。
⑸所有的叶子结点都出现在同一层次上,并且不带信息(可以看作是外部结点或查找失败的结点,实际上这些结点不存在,指向这些结点的指针为空)。 即所有叶节点具有相同的深度,等于树高度。
对于B-Tree索引,存储引擎在查找记录的时候不再是通过扫描全表来获取需要的数据么人是从索引的根节点进行搜索,根节点的槽中存放了指向子节点的指针,存储引擎根据这些指针向下查找。最后找到叶子节点。叶子节点比较特殊,他的指针指向的是索引的数据。而且不同的存储引擎实现也不一样。在mysql中MyISAM中指针指向的是数据的指针,而在InnoDB中,直接存放的是数据。
那么在什么情况下B-Tree可以使用索引呢?假设存在一张user表,我们对(“姓”,“名”,“出生日期”)建立符合索引,那么在B-Tree的key中就是按照姓,名,出生日期顺序存储的,这样方便我们理解下面这些情况:
1,全值匹配,指的是索引中的所有列进行匹配。比如 where 姓=‘张’ and 名=‘小凡’and 出生年月=‘1990-12-21’;
2,匹配最左前缀。比如查找 姓=‘张’,只能使用第一列。你想如果我们要名=‘三’,那么可以是‘赵三’,‘李三’索引中先根据姓排序,所以名=‘三’的根本没在一起,无法使用索引。
3,匹配列前缀 比如查找‘欧%’;
4,匹配范围值 可以使用索引列的第一列。
5,精确匹配某一列,在范围匹配另外一列。
根据B-Tree存储的特点,很容易知道有一些情况是没有办法使用索引的。比如如下情况:
1,不是按照索引列最左侧开始查找。
2,跳过中介的列。
3,如果某个列采用范围查找,那么右侧的列都没有办法使用索引。
B-Tree索引有一些独特的好处的,比如在B-Tree树的key中存放了索引列的值,所以如果我们只需要查询索引列的结果就可以直接使用索引而不需要去查找记录了。这就是覆盖索引的优化。
另外,因为B-Tree索引是有序的,所以除了查找之外,索引还可以用于查询中的order by 排序。
Hash索引
哈希索引是基于哈希表实现的。只有精确匹配索引所有列的的查询才有效。他的实现是存储殷勤会对每一行数据的索引列计算哈希码,并将哈希码和指向该记录的指针维护起来,对于hash相同的,采用链表的方式解决冲突。类似于hashmap。因为索引的结构是十分紧凑的,所以hash索引的查询很快。
但是hash索引也有他的限制:
1,hash索引只包含了哈希值和行指针,索引不能避免读取行,不能使用覆盖索引。
2,hash索引并不是按照索引顺序存储的,无法用于排序。
3,hash索引不支持部分或者区域查找,部分列的hash结果是不同的。
在Mysql中InnoDB引擎有一个特殊的功能叫做自适应哈希索引,他会在内存中基于B-Tree索引的基础上面创建一个哈希索引,这让B-Tree索引页具备了一些哈希索引的优点。
在《高性能的Mysql》这本树中,作者举了一个自定义哈希索引的列子。假设我们在一个表中大量存储了URL,而且需要根据URL来进行查找。因为URL比较长,这个时候如果我们使用B-Tree索引来,索引会非常的大。解决的办法是在列表中增加一个列,用来存放URL的哈希值,可以通过CRC32对URL进行计算,并存放在列表中,在查找的时候通过CRC32对url进行计算匹配列表中的hash值。
但是这个地方需要注意hash冲突的问题,所以在查询的时候需要添加url的匹配。
例如:where url_crc=CRC32(“http://www.cnblogs.com/yimixiong/p/7400914.html”) and url=” http://www.cnblogs.com/yimixiong/p/7400914.html”
以上是关于索引的分类--B-Tree索引和Hash索引的主要内容,如果未能解决你的问题,请参考以下文章
MySQL 进阶 索引 -- 索引概述索引结构(B+TreeHash)索引分类(聚集索引 二级索引 主键索引唯一索引常规索引全文索引)