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

简介: 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+树索引数据结构见下图:

image.png

(图片源自网络)

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


哈希索引的示意图则是这样的:

image.png

(图片源自网络)

简单地说,哈希索引就是采用一定的哈希算法,把键值换算成新的哈希值,检索时不需要类似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+树索引就可以了。

            </div>
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
机器学习/深度学习 人工智能 并行计算
5分钟掌握开源图神经网络框架DGL使用
近几年神经网络在人工智能领域的成功应用,让它备受关注和热捧。但是,它自身依然具有本质上的局限性,以往的神经网络都是限定在欧式空间内,这和大多数实际应用场景并不符合,因此,也阻碍了它在很多领域的实际落地应用。
5分钟掌握开源图神经网络框架DGL使用
|
缓存 监控 Linux
Linux性能分析利器:全面掌握perf工具
【10月更文挑战第18天】 在Linux系统中,性能分析是确保软件运行效率的关键步骤。`perf`工具,作为Linux内核自带的性能分析工具,为开发者提供了强大的性能监控和分析能力。本文将全面介绍`perf`工具的使用,帮助你成为性能优化的高手。
834 1
|
小程序 前端开发 JavaScript
微信小程序开发前端基础知识一
微信小程序开发前端基础知识一
417 0
|
存储 SQL 机器学习/深度学习
基于SLS平台与日志审计构建Cloud SIEM方案
本文介绍如何基于SLS平台与日志审计构建Cloud SIEM方案。
1965 0
|
存储 消息中间件 缓存
基于 MaxCompute 的实时数据处理实践
MaxCompute 通过流式数据高性能写入和秒级别查询能力(查询加速),提供EB级云原生数仓近实时分析能力;高效的实现对变化中的数据进行快速分析及决策辅助。当前Demo基于近实时交互式BI分析/决策辅助场景,实现指标卡近实时BI分析、近实时市场监测、近实时趋势分析、近实时销量拆分功能。
2148 1
基于 MaxCompute 的实时数据处理实践
|
前端开发
实用webpack插件之DefinePlugin
通过阅读这篇文章,可以学习到如何使用DefinePlugin插件使得前端项目更加工程化,说清晰点就是如何使用这个插件,在编译阶段根据NODE_ENV自动切换配置文件,提升前端开发效率。
实用webpack插件之DefinePlugin
|
iOS开发
iOS 状态栏的隐藏显示与状态栏样式的设置
iOS 状态栏的隐藏显示与状态栏样式的设置
1582 0
iOS 状态栏的隐藏显示与状态栏样式的设置
|
移动开发 弹性计算 前端开发
手把手教你开发互动游戏,看 EVA 互动技术体系在金币小镇的实践
EVA 是一套上手快、开发效率高、能力完善的互动研发体系,广泛应用在淘系的互动业务中。
手把手教你开发互动游戏,看 EVA 互动技术体系在金币小镇的实践
|
机器学习/深度学习 人工智能 自然语言处理
时在中春,大咖论道:机器之心AI科技年会干货集锦在这里
时在中春,阳和方起。3 月 23 日,机器之心 AI 科技年会以线上直播方式成功举办。
535 0
时在中春,大咖论道:机器之心AI科技年会干货集锦在这里
|
Java jvm-sandbox Shell
Jvm-Sandbox源码分析--模块刷新和卸载
Jvm-Sandbox源码分析--启动简析 Jvm-Sandbox源码分析--启动时加载模块 Jvm-Sandbox源码分析--增强目标类 在之前三篇文章中我们对jvm-sandbox相关逻辑做了一些分析,本篇文章将要分析一下刷新和卸载模块的逻辑。
3200 0