MySQL 索引结构采用 B+树原因

目录

为什么使用B+树而不是B树

B 树和 B+树的区别

红黑树 和 b+树的用途有什么区别


B 树是一种多路平衡树,用这种存储结构来存储大量数据,它的整个高度会相比二叉树来说,会矮很多。

而对于数据库而言,所有的数据都将会保存到磁盘上,而磁盘 I/O 的效率又比较低,特别是在随 机磁盘 I/O 的情况下效率更低。 所以 高度决定了磁盘 I/O 的次数,磁盘 I/O 次数越少,对于性能的提升就越大,这也是为什么 采用 B 树作为索引存储结构的原因,

Hash 哈希,只适合等值查询,不适合范围查询。

一般二叉树,可能会特殊化为一个链表,相当于全表扫描。

红黑树,一种特化平衡二叉树,MySQL 数据量很大时候,索引体积也会很大,内存放不下而从磁盘读取,树层次高话,读取磁盘次数就多了。

B-Tree,叶子节点和非叶子节点都保存数据,相同数据量,B+树更矮壮,也就说,相同数据量,B+树数据结构,查询磁盘次数会更少。

B+树只有叶子节点存放数据,而其他节点只存放索引,而 B 树每个节点都有 Data 域。所

以相同大小的节点 B+树包含的索引比 B 树的索引更多(因为 B 树每个节点还有 Data 域)

还有就是 B+树的叶子节点是通过链表连接的,所以找到下限后能很快进行区间查询,比 B

树中序遍历快

为什么使用B+树而不是B树

在 B 树中,键和值即存放在内部节点又存放在叶子节点;在 B+树中,内部节点只存键,叶子节点则同时存放键和值

B+树的叶子节点有一条链相连,而 B 树的叶子节点各自独立的。而 MySQL 的 InnoDB 存储引擎,它用了一种增强的 B 树结构,也就是 B+树来作为索引和数据 的存储结构。

B+树索引的所有数据均存储在叶子节点,而且数据是按照顺序排列的,链表连着的。那么 B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单(双向链表)

B+树的叶子节点是数据阶段用了一个链表串联起来,便于范围查找

B树非叶子节点上是不存储数据的,仅存储键值,而 B 树节点中不仅存储键值,也会存储数据。innodb 中页的默认大小是 16KB,如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找数据进行磁盘的 IO 次数有会再次减少,数据查询的效率也会更快.

相比较于 B 树结构来说,B+树做了两个方面的优化,如图所示

1、B+树的所有数据都存储在叶子节点,非叶子节点只存储索引

2、叶子节点中的数据使用双向链表的方式进行关联

1、从磁盘 I/O 效率方面来看:B+树的非叶子节点不存储数据,所以树的每一层就能够存储更多 的索引数量,也就是说,B+树在层高相同的情况下,比 B 树的存储数据量更多,间接会减少磁盘 I/O 的次数。

2、从范围查询效率方面来看:在 MySQL 中,范围查询是一个比较常用的操作,而 B+树的所有 存储在叶子节点的数据使用了双向链表来关联,所以 B+树在查询的时候只需查两个节点进行遍历就 行,而 B 树需要获取所有节点,因此,B+树在范围查询上效率更高。

3、从全表扫描方面来看:因为,B+树的叶子节点存储所有数据,所以 B+树的全局扫描能力更 强一些,因为它只需要扫描叶子节点。而 B 树需要遍历整个树。

4、从自增 ID 方面来看:基于 B+树的这样一种数据结构,如果采用自增的整型数据作为主键,还

能更好的避免增加数据的时候,带来叶子节点分裂导致的大量运算的问题。

总体来说,我认为技术方案的选型,更多的要根据具体的业务场景来决定,并不一定是说 B+树就

是最好的选择,就像 MongoDB 里面采用 B 树结构,本质上来说,其实是关系型数据库和非关系型数据

库的差异。

B+树有一个特点就是,非叶子节点存储的是目录项,而叶子节点存储的是数据项,因而可以通过二分查找快速定位到指定的数据项。在数据量比较大的前提下,适当的建立索引可以调高查询效率

需要先理解B+tree、红⿊树的实现原理。B+tree带有顺序访问指针,是红⿊树不具备的。

大致概括为以空间换时间,数据库在未添加索引的时候进行查询默认的是进行全量搜索,也就是进行全局扫描,有多少条数据就要进行多少次查询,然后找到相匹配的数据就把他放到结果集中,直到全表扫描完。而建立索引之后,会将建立索引的KEY值放在一个n叉树上(BTree)。因为B树的特点就是适合在磁盘等直接存储设备上组织动态查找表,每次以索引进行条件查询时,会去树上根据key值直接进行搜索,次数约为log总条数,底数为页面存储数,例如一个100万数据的表,页面存储数为100,那么有索引的查询次数为3次log1000000100,但是全量搜索为100万次搜索,这种方式类似于二分法,但是这个是n分法

B 树和 B+树的区别

B+树,其实是在 B 树的基础上做的增强,最大的区别有两个:

B 树的数据存储在每个节点上,而 B+树中的数据是存储在叶子节点,并且通过链表的方式把叶子节点中的数据进行连接B+树的子路数量等于关键字数这个是 B 树的存储结构,从 B 树上可以看到每个节点会存储数据

B+树的所有数据是存储在叶子节点,并且叶子节点的数据是用双向链表关联的

B 树和 B+树,一般都是应用在文件系统和数据库系统中,用来减少磁盘 IO 带来的性能损耗。

以 Mysql 中的 InnoDB 为例,当我们通过 select 语句去查询一条数据时,InnoDB需要从磁盘上去读取数据,这个过程会涉及到磁盘 IO 以及磁盘的随机 IO我们知道磁盘 IO 的性能是特别低的,特别是随机磁盘 IO。因为,磁盘 IO 的工作原理是,首先系统会把数据逻辑地址传给磁盘,磁盘控制电路按照寻址逻辑把逻辑地址翻译成物理地址,也就是确定要读取的数据在哪个磁道,哪个扇区。为了读取这个扇区的数据,需要把磁头放在这个扇区的上面,为了实现这一个点,磁盘会不断旋转,把目标扇区旋转到磁头下面,使得磁头找到对应的磁道,这里涉及到寻道事件以及旋转时间。很明显,磁盘 IO 这个过程的性能开销是非常大的,特别是查询的数据量比较多的情况下。所以在 InnoDB 中,干脆对存储在磁盘块上的数据建立一个索引,然后把索引数据以及索引列对应的磁盘地址,以 B+树的方式来存储。如图所示,当我们需要查询目标数据的时候,根据索引从 B+树中查找目标数据即可,由于 B+树分路较多,所以只需要较少次数的磁盘 IO 就能查找到。

为什么用 B 树或者 B+树来做索引结构?原因是 AVL 树的高度要比 B 树的高度要高,而高度就意味着磁盘 IO 的数量。所以为了减少磁盘 IO 的次数,文件系统或者数据库才会采用 B 树或者 B+树。

B 树:
(1)关键字集合分布在整颗树中;
(2)任何一个关键字出现且只出现在一个结点中;
(3)搜索有可能在非叶子结点结束;
(4)其搜索性能等价于在关键字全集内做一次二分查找;
B+树:
(1)有 n 棵子树的非叶子结点中含有 n 个关键字(b 树是 n-1 个),这些关键字不保存数据,只用来索引,所有数据都保存在叶子节点(b 树是每个关键字都保存数据);
(2)所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接;
(3)所有的非叶子结点可以看成是索引部分,结点中仅含其子树中的最大(或最小)关键字;
(4)通常在 b+树上有两个头指针,一个指向根结点,一个指向关键字最小的叶子结点;
(5)同一个数字会在不同节点中重复出现,根节点的最大元素就是 b+树的最大元素。
B+树相比于 B 树的查询优势磁盘读写代价更低 查询效率更加稳定 遍历所有的数据更方便
(1)B+树的中间节点不保存数据,所以磁盘页能容纳更多节点元素,更“矮胖”;
(2)B+树查询必须查找到叶子节点,B 树只要匹配到即可不用管元素位置,因此 B+树查找更稳定(并不慢);
(3)对于范围查找来说,B+树只需遍历叶子节点链表即可,B 树却需要重复地中序遍历

 

B 树是一种多路平衡查找树,为了更形象的理解。二叉树,每个节点支持两个分支的树结构,相比于单向链表,多了一个分支。二叉查找树,在二叉树的基础上增加了一个规则,左子树的所有节点的值都小于它的根节点,右子树的所有子节点都大于它的根节点。

二叉查找树会出现斜树问题,导致时间复杂度增加,因此又引入了一种平衡二叉树,它具有二叉查找树的所有特点,同时增加了一个规则:”它的左右两个子树的高度差的绝对值不超过 1“。平衡二叉树会采用左旋、右旋的方式来实现平衡。

而 B 树是一种多路平衡查找树,它满足平衡二叉树的规则,但是它可以有多个子树,子树的数量取决于关键字的数量,比如这个图中根节点有两个关键字 3和 5,那么它能够拥有的子路数量=关键字数+1。

因此从这个特征来看,在存储同样数据量的情况下平衡二叉树的高度要大于 B树

了解二叉树、AVL 树、B 树的概念

平衡二叉树

若左子树不空,则左子树上所有节点的值均小于它的根节点的值;

若右子树不空,则右子树上所有节点的值均大于或等于它的根节点的值;

每个非叶子节点的左右子树的高度之差的绝对值(平衡因子)最多为1。

B+树:所有的节点值都在最后叶节点上用双向链表连接在了一起

红黑树 和 b+树的用途有什么区别

红黑树多用在内部排序,即全放在内存中的,STL 的 map 和 set 的内部实现就是红黑树。

B+树多用于外存上时,B+也被成为一个磁盘友好的数据结构。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

思静语

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

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

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

打赏作者

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

抵扣说明:

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

余额充值