你还不知道 BTree,B-Tree,B+Tree 的区别吗?

文章目录

    • 前言
      • BTree
      • B+Tree
    • BTree 与 B+Tree

前言

关于MySQL的系列文章,请跳转至 MySQL专栏

今天来总结一下,B树、B-树、B+树,这三棵树。对于 B树和B-树,网上的说法分为两种,一种说法是B树是二叉搜索树,B-树是一种多路搜索树;另一种说法是 B树就是B-树,B-树就是B树。经过查阅资料,得出结论,后者说法是正确的。

下面引用百度百科 B树 的定义:

在B-树中查找给定关键字的方法是,首先把根结点取来,在根结点所包含的关键字K1,…,Kn查找给定的关键字(可用顺序查找或二分查找法),若找到等于给定值的关键字,则查找成功;否则,一定可以确定要查找的关键字在Ki与Ki+1之间,Pi为指向子树根节点的指针,此时取指针Pi所指的结点继续查找,直至找到,或指针Pi为空时查找失败。

在这里插入图片描述

再来看看百度百科中 B-树 的定义:

在计算机科学中,B树(英语:B-tree)是一种自平衡的树,能够保持数据有序。这种数据结构能够让查找数据、顺序访问、插入数据及删除的动作,都在对数时间内完成。B树,概括来说是一个一般化的二叉查找树(binary search tree),可以拥有多于2个子节点。与自平衡二叉查找树不同,B树为系统大块数据的读写操作做了优化。B树减少定位记录时所经历的中间过程,从而加快存取速度。B树这种数据结构可以用来描述外部存储。这种数据结构常被应用在数据库和文件系统的实现上。

综上所述,B-树是B树的别名,二者指的是一棵树。


介绍 BTree 前先介绍一下熟悉的二叉搜索树。
  • 若任意结点的左子树不空,则左子树上所有结点的值均不大于它的根结点的值
  • 若任意结点的右子树不空,则右子树上所有结点的值均不小于它的根结点的值。
  • 任意结点的左、右子树也分别为二叉搜索树。

而二叉搜索树会出现极端的情况,如下图右图。

你还不知道 BTree,B-Tree,B+Tree 的区别吗?_第1张图片

很显然,右图中的搜索性能是线性的了,所以使用二叉搜索树要尽可能让树保持左图的结构,更平衡。

实际使用的二叉搜索树都是在原二叉搜索树的基础上加上平衡算法,即“平衡二叉树”。


BTree

BTree 是一种平衡多叉树。

了解BTree的性质前,先来理解两个概念:

  • 度数:在树中,每个节点的子节点的个数称为该节点的度数
  • 阶数:一个节点的子节点的数目的最大值

一棵 m 阶B树是一棵平衡的m路搜索树,它有以下性质:

  • 根节点至少有两个子节点
  • 每个非根节点所包含的关键字个数 j 满足:┌ m/2 ┐ - 1 <= j <= m - 1;
  • 除根结点以外的所有非叶子结点的度数正好是关键字总数加1,故内部子树个数 k 满足:┌ m/2 ┐ <= k <= m ;
  • 所有的叶子结点都位于同一层

如下图,是一棵3阶的BTree
你还不知道 BTree,B-Tree,B+Tree 的区别吗?_第2张图片

来模拟下查找单个元素17的过程:

  • 根据根节点指针找到文件目录的根磁盘块1,将其中信息导入内存【1次磁盘I/O】
  • 此时内存中有两个文件,名为13和31,和三个存储其他磁盘页面地址的数据,根据算法发现, 13<17<31,因此找到根节点中存储的第二个指针
  • 根据第二个指针,定位到磁盘块3,并将其中信息导入内存【2次磁盘I/O】
  • 此时内存中有一个文件名为18,和两个存储其他磁盘页面地址的数据,根据算法发现,17<18,因此找到元素为18的节点的第一个指针
  • 根据第一个指针,定位到磁盘块7,并将其中信息导入内存【3次磁盘I/O】
  • 此时内存中有两个文件,名为14,17,我们根据算法查找到文件 17,并定位了该文件内存的磁盘地址

来模拟下范围查找元素 17-35 的过程:

  • 首先,自顶向下查找到范围的下限,元素17
  • 中序遍历到元素 18
  • 中序遍历到元素 23
  • 中序遍历到元素 31
  • 中序遍历到元素 35 ,遍历结束

上述描述了BTree 数据结构查询单个元素和范围查询元素的流程。

相同数量的元素在BTree 中生成的节点要远远小于二叉树中的节点,相差的节点数量就等同于磁盘I/O次数,这样达到一定数量后,性能就有很大差异了。

B+Tree

B+Tree 也是一种多路搜索树,通常用于数据库和操作系统的文件系统中,特点是能够保持数据稳定有序,其插入与修改拥有较稳定的时间复杂度。

对于一棵m阶的B+Tree,它有以下性质:

  • 每个节点最多有m个子节点
  • 除根节点外,每个节点最少有 [m/2] 个子节点,根节点至少有2个子节点
  • 有k个子节点的节点必有k个关键字

你还不知道 BTree,B-Tree,B+Tree 的区别吗?_第3张图片

看图可知 B+Tree 和 BTree 对比,B+Tree 的所有数据都存在了叶子节点,并且叶子节点组成了一个链表。

来模拟下B+Tree查找单个元素17的过程:

我们还是来查找元素17,它的遍历过程和BTree 是相同的,但它比BTree更高效,因为 B+Tree 中非叶子节点仅仅是索引,没有数据元素,所以同样的磁盘页可以容纳更多的节点元素。这就意味着,相同的情况下,B+Tree 的结构比 BTree 更加“矮胖”,因此查询时 I/O 次数也更少。


来模拟下B+Tree范围查找元素 17-35 的过程

  • 自顶向下,查找到范围的下限 元素17
  • 通过链表指针,遍历到元素 18
  • 通过链表指针,遍历到元素 23
  • 通过链表指针,遍历到元素 31
  • 通过链表指针,遍历到元素 35

B+Tree 的范围查找直接通过叶子节点组成的链表查找即可,效率比BTree 要高的多。


BTree 与 B+Tree

  • 数据量相同的情况下,B+Tree的查询性能比BTree更好,I/O操作更少
  • BTree 的查找性能不稳定,最好情况是只查根节点,最坏情况是查到叶子节点;而B+Tree的查找都要查到叶子节点,所以每一次查找都是稳定的
  • 范围查询中,BTree的查询性能远不如B+Tree,因为BTree 是查找到范围的下限后,做树的中序遍历;而B+Tree是查找到范围的下限后,直接通过叶子节点的链表指针查找范围内的元素。

你可能感兴趣的:(MySQL)