【重难点】【MySQL 04】Hash索引和B+树索引、MySQL 索引为什么使用B+树

【重难点】【MySQL 04】索引的基本原理、Hash索引和B+树索引、数据库为什么使用B+树而不是B树

一、Hash索引和B+树索引

数据结构

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

在 B+ 树上的常规检索,从根结点到叶子结点的搜索效率基本相当,不会出现大幅波动,而且基于索引的顺序扫描时,也可以利用双指针快速左右移动,效率非常高。因此,B+ 树索引被广泛应用于数据库、文件系统等场景

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

对比

  • 如果是等值查询,那么 Hash 索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值。当然了,这个前提是,键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据
  • 如果是范围查询检索,这时候 Hash 索引就毫无用武之地了,因为原先是有序的键值,经过 Hash 算法后,顺序都打乱了,就没办法再利用索引完成范围查询检索
  • 同理,Hash 索引也无法利用索引完成排序,以及 like 这样的部分模糊查询,这种部分模糊查询其实本质上也是范围查询
  • Hash 索引不支持复合索引,对于复合索引来说,Hash 索引再计算 Hash 值的时候是将索引键合并后再一起计算 Hash 值,不会针对每个索引单独计算 Hash 值。因此,如果用到复合索引的一个或者几个索引时,索引会失效
  • B+ 树索引的关键字检索效率比较平均,不像 B 树那样波动幅度大,在有大量重复键值的情况下,Hash 索引的效率也是极低的,因为存在哈希冲突问题

应用场景

通常,B+ 树索引结构适用于绝大多数场景

如果数据离散型高、基数大,且为等值查询的时候,Hash 索引特别有优势

二、MySQL 索引为什么使用B+树

1.B树

思考为什么使用 B+ 树之前我们先思考为什么要使用树结构存储?我直接给出答案吧,因为树的查询效率高,而且可以保持有序

如果需要查询效率高,二叉查找树不是更好的选择,为什么要使用 B 树呢?这就需要好好分析了

二叉查找树查询的时间复杂度是 O(logN),性能已经足够高了,从算法逻辑上来讲,二叉查找树的查找速度和比较次数都是最小的,但是数据库需要考虑一个现实问题:磁盘 IO。数据库索引是存储在磁盘上的,当数据量比较大的时候,索引可能有几个 G 甚至更多。当我们利用索引查询的时候,显然不能把整个索引全部加载到内存,我们能做的只有逐一加载每一个磁盘页,这里的磁盘页对应着索引树的结点
在这里插入图片描述
在这里插入图片描述
如果我们利用二叉查找树作为索引结构,那么我们每判断一次就要进行一次磁盘 IO,最坏的情况是我们要查找的数据在叶子结点,也就是说磁盘 IO 的次数是由树的高度决定的。既然如此,我们就需要降低树结构的高度,从而减少磁盘 IO 次数,把原本 “瘦高” 的树结构变得 “矮胖”,这就是 B 树的特征之一

B 树介绍

B 树(Balance Tree)是一种多路平衡查找树,它的每一个结点最多包含 k 个孩子,k 被称为 B 树的阶,k 的大小取决于磁盘页的大小

一个 m 阶的 B 树具有如下几个特征:

  1. 根结点至少有两个子结点
  2. 每个中间结点都包含 k - 1 个元素和 k 个子结点,其中 m/2 <= k <= m
  3. 每一个叶子结点都包含 k - 1 个元素,其中 m/2 <= k <= m
  4. 所有的叶子结点都位于同一层
  5. 每个结点中的元素从小到大排列,结点当中 k - 1 个元素正好是 k 个子结点包含的元素的值域分划
    在这里插入图片描述

B 树在查询中的比较次数其实不比二叉查找树少,尤其当单一结点中的元素数量很多时,可是相比磁盘 IO 的速度,内存中的比较耗时几乎可以忽略。所以只要树的高度足够低,IO 次数足够少,就可以提升查找性能。因此,结点内部元素多一些也没有关系,仅仅是多了几次内存交互,只要不超过磁盘页的大小即可,这就是 B 树的优势之一

B 树无论是插入还是删除,B 树始终能维持多路平衡,这时 B 树的一大优势

至此,我们了解了 B 树相较于其它树结构的优势。B 树主要应用于文件系统,其实部分数据库索引用的就是 B 树,而不是 B+ 树,比如著名的非关系型数据库 MongoDB

而大部分关系型数据库,比如 MySQL 则使用 B+ 树作为索引,这也就回到了我们的主题,为什么 MySQL 索引使用 B+ 树?

2.B+ 树

同样,我们还是先介绍一下 B+ 树的概念

B+ 树介绍

B+ 树是基于 B 树的一种变体,有着比 B 树更高的查询性能

一个 m 阶的 B+ 树具有如下几个特征:

  1. 有 k 个子树的中间结点包含有 k 个元素(B 树是 k - 1),每个元素不保存数据,只用来索引,所有数据都保存在叶子结点
  2. 所有的叶子节点中包含了全部元素的信息,以及指向含有这些元素记录的指针,且叶子结点本身依据关键字的大小从小到大地链接
  3. 所有的中间结点元素都同时存在于子结点,在子结点元素中是最大或最小元素
    在这里插入图片描述

B+ 树还具有一个特点,这个特点是在索引之外,却是至关重要的特点,那就是卫星数据(Satellite Information)的位置。所谓卫星数据,指的是索引元素所指向的数据记录,比如数据库中的某一行。在 B 树中,无论中间结点还是叶子结点都带有卫星数据,而在 B+ 树中,只有叶子结点带有卫星数据,其余中间结点仅仅是索引没有任何数据关联,如下两张图可以清晰地看出两者的区别:

在这里插入图片描述
在这里插入图片描述

补充一点:在数据库的聚簇索引中,叶子结点直接包含卫星数据;在非聚簇索引中,叶子结点带有指向卫星数据的指针

B 树与 B+ 树的对比

在单行查询的时候,B+ 树会自顶向下逐层查找结点,最终找到匹配的叶子结点。这看起来和 B 树差不多,但其实有两点不同。首先,B+ 树的中间结点没有卫星数据,所以同样大小的磁盘页可以容纳更多的结点元素,这就意味着,数据量相同的情况下,B+ 树的结构比 B 树更加 “矮胖”,因此查询时 IO 次数也更少。其次,B+ 树的查询必须最终查找到叶子结点,而 B 树只要找到匹配元素即可,无论匹配元素处于中间结点还是叶子结点。因此,B 树的查找性能并不稳定(最好情况是只查根结点,最坏情况是查到叶子结点)。而 B+ 树的每一次查找都是稳定的

我们再来看看范围查询。B 树做范围查询只能依靠繁琐的中序遍历,而 B+ 树只需要在链表上做遍历即可:即先自顶向下找到范围的下限,再通过链表指针遍历到目标元素

除了查询,还有插入和删除操作,因为 B+ 树的叶子结点包含所有元素,并且以有序的链表结构存储,这样大大提高了增删结点的效率

综上,B+ 树相比 B 树的优势:

  1. 磁盘 IO 次数更少
  2. 查询性能稳定
  3. 范围查询简便
  4. 增删结点时,效率更高
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: MySQL 使用 B-Tree 而不是 Hash 索引是因为 B-Tree 有许多优点。 1. 支持排序:B-Tree 索引可以支持排序,因此支持顺序查找。Hash 索引则不能支持排序,因此只支持随机查找。 2. 支持范围查询:B-Tree 索引可以支持范围查询,因此支持区间查询,而 Hash 索引则不能。 3. 支持分块查询:B-Tree 索引使用分块查询,因此可以支持大数据量的查询,而 Hash 索引则不能。 4. 支持磁盘存储:B-Tree 索引可以使用磁盘存储,因此占用内存较少,而 Hash 索引则需要使用内存,因此内存占用较多。 因此,B-Tree 索引Hash 索引更适合用于大数据量的数据库系统,特别是在排序和范围查询等方面。 ### 回答2: MySQL使用B-tree而不是Hash索引是为了更好地支持范围查询和排序操作。Hash索引是基于哈希算法的索引,它将索引值直接映射到哈希表的位置,可以实现非常快速的查找操作。但是,它并不适合处理范围查询和排序操作。 首先,Hash索引是无序的,无法支持范围查询。范围查询需要按一定的顺序访问索引的数据,而Hash索引无法提供这样的顺序。 其次,Hash索引在处理排序操作时效率较低。排序操作需要根据索引的数据值进行排序,但是Hash索引的数据值是无序的,因此需要额外的操作来实现排序。 而B-tree索引是一种平衡的树状数据结构,可以支持按范围查询和排序操作。B-tree索引索引值按顺序组织在树的节点,可以在树的节点之间进行高效的跳跃和遍历,从而实现快速的范围查询和排序操作。 此外,B-tree索引适用于磁盘存储,而不仅仅是内存存储。数据库的数据通常存储在磁盘上,而不是全部加载到内存。B-tree索引的结构特性能够适应磁盘存储的特点,减少磁盘IO次数,提高索引的检索效率。 综上所述,为了更好地支持范围查询和排序操作,并适应磁盘存储的特点,MySQL选择使用B-tree而不是Hash索引。 ### 回答3: MySQL索引使用B树而不是哈希的主要原因有三个。 首先,B树适合磁盘存储,而哈希适合内存存储。在磁盘上,数据是分块存储的,每个块可以容纳多个数据。B树的结构能够更有效地利用磁盘上的块,减少磁盘I/O次数,提高数据的读取效率。而哈希则不适合磁盘存储,因为哈希表需要一次完成整个表的读取,对于大型数据量的表来说,哈希表会导致大量的磁盘I/O,性能较差。 其次,B树适合范围查询,而哈希不适合。在MySQL,经常需要使用范围查询,如大于、小于、区间等。B树的有序特性使得范围查询非常高效,只需要遍历指定范围的节点即可。而哈希表的数据分布是随机的,无法提供有序性,无法高效地支持范围查询。 最后,B树支持数据的顺序访问,而哈希不支持。B树的左子树保存的是小于父节点的数据,右子树保存的是大于父节点的数据,这种有序性使得B树能够很好地支持数据的顺序访问。而哈希表的数据分布是随机的,无法提供有序性,不能有效地支持数据的顺序访问。 综上所述,由于MySQL索引需要适应磁盘存储、范围查询和数据的顺序访问,B树是一种更适合的数据结构,而哈希表在这些方面表现较差,因此MySQL索引选择使用B树而不是哈希。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

313YPHU3

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值