其它高阶数据结构⑥_B+树和B*树_B树系列在MySQL的应用

目录

1. B+树

1.1 B+树的概念

1.2 B+树的查找和插入

1.3 B+树和B树的对比

2. B*树的概念和特点

3. B树系列在MySQL的应用

3.1 MySQL索引简介

3.2 MyISAM

3.3 InnoDB

本篇完。


1. B+树

1.1 B+树的概念

        前一篇博客已经介绍了B树及其实现代码,B+树是B树的变形,是在B树基础上优化的多路平衡搜索树,B+树的规则跟B树基本类似,但是又在B树的基础上做了一些改进优化。

一棵m阶的B+树需满足下列条件:

  1. 每个分支结点最多有m棵子树(孩子结点)。
  2. 非叶根结点至少有两棵子树,其它每个分支结点至少有「m/2]棵子树。(前面这两条其实还跟B树是一样的,下面就不一样了)
  3. 结点的子树个数与关键字个数相等。
  4. 结点的子树指针p[i]指向关键字值大小在[k[i],k[i+1])区间之间。
  5. 所有叶子节点增加一个链接指针链接在一起。
  6. 所有关键字及其映射数据都在叶子节点出现。

B+树的特性:

  1. 所有关键字都出现在叶子节点的链表中,且链表中的元素都是有序的。
  2. 查找不可能在分支节点中命中。
  3. 分支节点相当于是叶子节点的索引(仅含有其子树根结点中最大/最小关键码,我们这里图中是最小的),叶子节点才是存储数据的数据层(与B树不同)。

1.2 B+树的查找和插入

        还是以这棵B+树为例,比如我们要查找33,从根结点开始33比5大,往后走,比28也大,再往后走,但是比65小。

        所以如果33存在的话,应该在28的子树中。所以进入28的子树中,然后比较比28大,比35小,所以再往这一层的28的子树p1中找,这就进入到叶子结点的链表中,往后遍历就找到了33。(如果查找的是28也要进入到叶子结点的链表中查找,即使分支结点中存在)

        那如果查找34(找不到),也是一样的,最终走到叶子结点的链表中,但是没有这个元素,所以就找不到。

        所以B+树的查找无论成功与否,都要走到最下面一层的叶子结点,而B树的话,查找可能停止在任意一层。

除了上面的查找方法,B+树还有另外一种查找方法:

        上面提到对于B+树来说,所有叶子节点增加一个链接指针链接在一起。而每个叶子结点的链表里面元素都是有序的。所以我们也可以通过这个链接指针去进行顺序查找,从前往后遍历每一个叶子结点的链表。

        分支节点可以看成是叶子节点的索引,链接指针存在的意义就是便于遍历所有数据,通过叶子节点的指针可以访问兄弟叶子节点,进而遍历数据。  

        插入数据时,如果叶子节点元素满了就创建一个新节点,并将数据的后一半给新节点,在父节点中记录新节点第一个数据并建立指针联系。

拓展,B+树的插入操作规则如下:

  • 查找插入位置:从根节点开始,按照B+树的搜索规则找到插入位置。如果插入的关键字已经存在于树中,则根据具体情况进行处理(如替换、忽略或合并等)。
  • 插入到叶子节点:将新的关键字插入到叶子节点中的适当位置。如果插入后导致叶子节点的关键字数量超过了阶数的上限,则进行分裂操作。
  • 叶子节点分裂:将超过阶数上限的叶子节点分裂成两个节点。将一半的关键字移动到新的节点中,并调整指针连接。同时,将新节点的最小关键字插入到父节点中。
  • 父节点调整:如果叶子节点的分裂导致父节点关键字数量超过了阶数的上限,则进行递归的分裂操作。将超过阶数上限的父节点分裂成两个节点,并将新节点的最小关键字插入到父节点的父节点中。
  • 递归调整:如果父节点的分裂导致祖先节点关键字数量超过了阶数的上限,则继续进行递归的分裂操作,直到根节点。
  • 根节点分裂:如果根节点的分裂导致树的高度增加,则创建一个新的根节点,并将原来的根节点分裂成两个节点。将新的根节点的最小关键字插入到新的根节点中,并调整指针连接。

1.3 B+树和B树的对比

结论:

  1. B树更适合随机查找,B+树更适合范围查找。
  2. B+树相对更省空间。
  3. 对数据进行插入、删除的时候B+树效率更高。

原因:

        B树的每个节点包含关键字和对应的指针,用于存储数据和构建索引。B树的节点可以直接存储数据,因此在查找时可以直接定位到数据所在的节点。

        B+树的每个节点只包含关键字,数据存储在叶子节点中。叶子节点之间通过指针连接形成一个有序链表,叶子节点上的关键字也构成一个有序序列。B+树的非叶子节点仅用于索引,不存储数据,这样可以减少非叶子节点的数量,提高内存利用率。

        B树的节点既存储数据又存储索引,因此每个节点可以存储更多的数据。这样可以减少树的高度,提高查询效率。但是,由于B树的节点包含数据,插入和删除操作需要进行数据的移动和调整,相对较慢。

        B+树的非叶子节点仅用于索引,不存储数据,因此每个节点可以存储更多的索引。叶子节点之间通过指针连接形成有序链表,可以高效地进行顺序访问。同时,由于B+树的数据只存储在叶子节点中,插入和删除操作只需要调整索引节点,相对较快


2. B*树的概念和特点

B*树是B+树的变形,在B+树的非根和非叶子节点再增加指向兄弟节点的指针。

B*树的特点: B*树空间利用率比B+树高。

        B+树的分裂:当一个结点满时,分配一个新的结点,并将原结点中1/2的数据复制到新结点,最后在父结点中增加新结点的指针。

        B*树的分裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了)。如果兄弟也满了,则在原结点与兄弟结点之间增加新结点,并各复制1/3的数据到新结点,最后在父结点增加新结点的指针。

        B*树在进行页分裂和合并的时候会优先考虑兄弟节点是不是还没有满,所以分配新结点的概率比B+树要低,所以空间使用率更高。

  • B树:有序数组+平衡多叉树;
  • B+树:有序数组链表+平衡多叉树;
  • B*树:一棵更丰满的,空间利用率更高的B+树。

在实际使用中,空间一般都足够,所以B+树的使用是最多的。


3. B树系列在MySQL的应用

跟着专栏序号学过来的话,到这应该也学过MySQL了,不过也简单介绍一下MySQL的索引。

MySQL数据库⑧_索引(概念+理解+操作)_mysql 索引层高估计-CSDN博客

3.1 MySQL索引简介

        B树最常见的应用就是用来做索引。索引通俗的说就是为了方便用户快速找到所寻之物,比如:书籍目录可以让读者快速找到相关信息,网页的导航网站,为了让用户能够快速的找到有价值的分类网站。本质上就是互联网页面中的索引结构。

        MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获取数据的数据结构,简单来说:索引就是数据结构。

        当数据量很大时,为了能够方便管理数据,提高数据查询的效率,一般都会选择将数据保存到数据库,因此数据库不仅仅是帮助用户管理数据,而且数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用数据,这样就可以在这些数据结构上实现高级查找算法,该数据结构就是索引。

        MySQL是目前非常流行的开源关系型数据库,不仅是免费的,可靠性高,速度也比较快,而且拥有灵活的插件式存储引擎。如下:

MySQL中索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的。


3.2 MyISAM

        MyISAM引擎是MySQL5.5.8版本之前默认的存储引擎,不支持事务,支持全文检索,使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。

        MySQL中的MyISAM引擎就是使用B+树,主键和辅键索引结构相同,只不过主键不能重复,索引数据时,通过B+树的搜索方式(与B树基本相同,不同的是可以通过链接指针直接访问下一个叶子节点)找到key值,通过key值找到数据地址,再通过地址访问数据,即非聚集索引

图例来源(有修改):CodingLabs - MySQL索引背后的数据结构及算法原理

        MyISAM引擎其结构如下:

        上图是以以Col1为主键,MyISAM的示意图,可以看出MyISAM的索引文件仅仅保存数据记录的地址。在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。如果想在Col2上建立一个辅助索引,则此索引的结构如下图所示:

        同样也是一棵B+Tree,data域保存数据记录的地址。因此,MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。MyISAM的索引方式也叫做“非聚集索引”的


3.3 InnoDB

        InnoDB存储引擎支持事务,其设计目标主要面向在线事务处理的应用,从MySQL数据库5.5.8版本开始,InnoDB存储引擎是默认的存储引擎。InnoDB支持B+树索引、全文索引、哈希索引。但InnoDB使用B+Tree作为索引结构时,具体实现方式却与MyISAM截然不同。

        第一个区别是InnoDB的数据文件本身就是索引文件。MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而InnoDB索引,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此,InnoDB表数据文件本身就是主索引。

        上图是InnoDB主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录,这种索引叫做聚集索引。因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整型。

        第二个区别是InnoDB的辅助索引data域存储相应记录主键的值而不是地址,所有辅助索引都引用主键作为data域。

        聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。


本篇完。

下一篇是跳表的内容。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

GR鲸鱼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值