开发者社区> 晚来风急> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

FAQ系列 | B+树索引和哈希索引的区别

简介:
+关注继续查看

导读

在MySQL里常用的索引数据结构有B+树索引和哈希索引两种,我们来看下这两种索引数据结构的区别及其不同的应用建议。

二者区别

备注:先说下,在MySQL文档里,实际上是把B+树索引写成了BTREE,例如像下面这样的写法:

CREATE TABLE t(
aid int unsigned not null auto_increment,
userid int unsigned not null default 0,
username varchar(20) not null default ‘’,
detail varchar(255) not null default ‘’,
primary key(aid),
unique key(uid) USING BTREE,
key (username(12)) USING BTREE  此处 uname 列只创建了最左12个字符长度的部分索引
)engine=InnoDB;

一个经典的B+树索引数据结构见下图:
0?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1
(图片源自网络)

B+树是一个平衡的多叉树,从根节点到每个叶子节点的高度差值不超过1,而且同层级的节点间有指针相互链接。

在B+树上的常规检索,从根节点到叶子节点的搜索效率基本相当,不会出现大幅波动,而且基于索引的顺序扫描时,也可以利用双向指针快速左右移动,效率非常高。

因此,B+树索引被广泛应用于数据库、文件系统等场景。顺便说一下,xfs文件系统比ext3/ext4效率高很多的原因之一就是,它的文件及目录索引结构全部采用B+树索引,而ext3/ext4的文件目录结构则采用Linked list, hashed B-tree、Extents/Bitmap等索引数据结构,因此在高I/O压力下,其IOPS能力不如xfs。

详细可参见:

https://en.wikipedia.org/wiki/Ext4
https://en.wikipedia.org/wiki/XFS


哈希索引的示意图则是这样的:
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=
(图片源自网络)

简单地说,哈希索引就是采用一定的哈希算法,把键值换算成新的哈希值,检索时不需要类似B+树那样从根节点到叶子节点逐级查找,只需一次哈希算法即可立刻定位到相应的位置,速度非常快。

从上面的图来看,B+树索引和哈希索引的明显区别是:

  • 如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值;当然了,这个前提是,键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据;

  • 从示意图中也能看到,如果是范围查询检索,这时候哈希索引就毫无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索;

  • 同理,哈希索引也没办法利用索引完成排序,以及like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询);

  • 哈希索引也不支持多列联合索引的最左匹配规则

  • B+树索引的关键字检索效率比较平均,不像B树那样波动幅度大,在有大量重复键值情况下,哈希索引的效率也是极低的,因为存在所谓的哈希碰撞问题

后记

在MySQL中,只有HEAP/MEMORY引擎表才能显式支持哈希索引(NDB也支持,但这个不常用),InnoDB引擎的自适应哈希索引(adaptive hash index)不在此列,因为这不是创建索引时可指定的。

还需要注意到:HEAP/MEMORY引擎表在mysql实例重启后,数据会丢失。

通常,B+树索引结构适用于绝大多数场景,像下面这种场景用哈希索引才更有优势:

在HEAP表中,如果存储的数据重复度很低(也就是说基数很大),对该列数据以等值查询为主,没有范围查询、没有排序的时候,特别适合采用哈希索引

例如这种SQL:
SELECT … FROM t WHERE C1 = ?; — 仅等值查询

在大多数场景下,都会有范围查询、排序、分组等查询特征,用B+树索引就可以了。


文章转自老叶茶馆公众号,原文链接:https://mp.weixin.qq.com/s/waNB3pn1kSyLBk-c0jRvNQ

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
FAQ系列 | B+树索引和哈希索引的区别
FAQ系列 | B+树索引和哈希索引的区别
20 0
FAQ系列 | B+树索引和哈希索引的区别
FAQ系列 | B+树索引和哈希索引的区别
20 0
FAQ系列 | B+树索引和哈希索引的区别
FAQ系列 | B+树索引和哈希索引的区别
12 0
FAQ系列 | B+树索引和哈希索引的区别
FAQ系列 | B+树索引和哈希索引的区别
28 0
FastAPI 学习之路(二十九)使用(哈希)密码和 JWT Bearer 令牌的 OAuth2
FastAPI 学习之路(二十九)使用(哈希)密码和 JWT Bearer 令牌的 OAuth2
94 0
JAVAWeb| 详解JSP技术、指令、隐式对象、标签
JAVAWeb| 详解JSP技术、指令、隐式对象、标签
48 0
Java架构师教你写代码(二) - 使用建造者替代多参数的构造器(下)
Java架构师教你写代码(二) - 使用建造者替代多参数的构造器(下)
42 0
Day 6:在 Java 虚拟机上使用 Grails 进行快速 Web 开发
Grails 是一个基于 Groovy 和 Java 的开源 Web 框架。它是 Java 虚拟机(JVM)上顺应 Rails、Django 等流行 Web 框架而生的,伴随着标准的 Jetty/Tomcat 服务器,Grails 能帮助开发者进行快速的应用开发。在这篇文章中,我们会描述如何用 Grails 的 Eclipse 插件开发一个简单的 Web 应用。
66 0
+关注
9363
文章
243
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载