B树和B+树MySQL为什么用B+树?

文章目录

  • B树和B+树
    • B树
      • B树的定义
      • B树的插入操作
      • 删除操作
    • B+树
      • B+树的定义
      • B+树的插入操作
      • 删除操作
  • B树和B+树的区别?
  • MySQL数据库为啥用B+树作为索引,而不用B树?

B树和B+树

原文链接:https://blog.csdn.net/jinking01/article/details/115130286

B树

B树的定义

B树也称为B-树,是一颗多路平衡查找树。描述B树的时候需要确定它的阶数,阶数表示一个节点最多可以有几个孩子,一般用m表示。当m=2时,就是二叉搜索树。

对于m阶B树定义如下:

  1. 每个结点最多有m-1个关键字。
  2. 根结点可以只有一个关键字。
  3. 非根节点中至少有Math.ceil(m/2)-1个关键字。
  4. 每个节点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的值都小于它,每个右子树的值都大于它。
  5. 所有叶子节点都位于同一层。

在这里插入图片描述

如图是一个4阶B树,每个节点最多个m-1= 3个关键字,非叶子节点至少有Math.ceil(m/2)-1=1个关键字。

B树的插入操作

如果B树中已经存在需要插入的值,则替换掉。如果没有直接添加。

添加步骤如下:

  1. 根据插入的值找到叶子节点并插入。
  2. 判断当前节点的个数是否小于等于m-1,满足结束,否则进行下一步
  3. 以节点中间值(如果是偶数个时选择前一个或者后一个都可以)为中心分裂成左右两个部分,然后将中间值插入到父节点中,插入到父节点后这个中间值左子树指向左半部分,右子树指向右半部分,然后当前节点指向父节点,继续进行第三步。

下面以4阶数为例

先在根节点中插入20、39、91

在这里插入图片描述

在插入40

在这里插入图片描述

节点的关键字个数为4大于m-1,按照第三步:我们选择前一个提取。
在这里插入图片描述

插入53,21

在这里插入图片描述

插入40

在这里插入图片描述

插入节点关键字个数大于m-1,需要分裂:

在这里插入图片描述

插入30,27

在这里插入图片描述

插入33

在这里插入图片描述

插入35

在这里插入图片描述

添加35后分裂得到上图,30插入到父节点后,父节点被称为当前节点,当前节点关键字多了。分裂得到:

在这里插入图片描述

删除操作

如果B树中不存在要删除的值则失败。

  1. 当前需要删除的值在非叶子节点上,则用后续的值替换当前位置。然后在后继节点中删除后继值。此时如果后继节点的关键字个数如果大于等于Math.ceil(m/2)-1,删除结束,否则执行下一步。
  2. 如果兄弟结点key个数大于Math.ceil(m/2)-1,则父结点中的key下移到该结点,兄弟结点中的一个key上移,删除操作结束。否则,将父结点中的key下移与当前结点及它的兄弟结点中的key合并,形成一个新的结点。原父结点中的key的两个孩子指针就变成了一个孩子指针,指向这个新结点。然后当前结点的指针指向父结点,重复上第2步。

下面以5阶B树为例删除:

原数据如下
在这里插入图片描述

删除21:删除21后判断当前节点的关键字个数大于等于Math.ceil(m/2)-1,删除结束。

在这里插入图片描述

删除27:27为非叶子节点上的值,所以利用后继记录28替换他。
在这里插入图片描述

从图中看出,28替换后原28所在节点的关键字个数小于Math.ceil(m/2)-1。删但是它的兄弟节点有富裕的关键字(也就是兄弟节点关键字个数大于Math.ceil(m/2)-1)。向兄弟节点借一个。所以28下移,26上移。

在这里插入图片描述

删除24:在叶子节点直接删除24

在这里插入图片描述

发现当前节点关键字个数小于Math.ceil(m/2)-1,此时兄弟节点也只有两个关键字,不能借,只能父节点下沉与两个子节点组成新的节点。

在这里插入图片描述

删除40:直接删除后:

在这里插入图片描述

同删除24一样,父节点值下沉:

在这里插入图片描述

发现父节点的关键字又小于Math.ceil(m/2)-1,父节点的兄弟节点也不能借,父节点的父节点下沉。

在这里插入图片描述

B+树

B+树的定义

在这里插入图片描述

B树和B+树十分类似,B+树的所有叶子节点是链通的(下文中为了画图方便没有体现链接),B+树的关键字个数=最大孩子个数-1;B+树就是将所有数据存储在叶子节点上,非叶子节点只用于索引。上图为4阶B+树,黑色为索引。彩色为叶子节点存储真正的数据。

B+树的插入操作

  1. 若为空树,创建节点,直接插入值,此时节点也为根节点。
  2. 针对叶子类型节点:根据值找到待插入的叶子节点位置。插入后判断节点的值的个数是否小于m-1,是则插入结束,不是则将这个叶子节点分裂成两个叶子节点,左叶子节点包含前m/2个记录,右节点包含剩下的记录,将第m/2+1个记录值放进父节点,然后执行下一步。
  3. 针对索引节点:如果当当前节点记录个数小于等于m-1,插入结束。否则,将这个索引类型节点分裂成两个,左索引节点包含(m-1)/2个记录,右节点树包含m-(m-1)/2个记录,第m/2个节点插入到父节点中。重复第三步。

以5阶B+树为例:

首先依次插入:8,15,5,10
在这里插入图片描述

插入16:在当前节点插入16后:

在这里插入图片描述

发现节点的记录值大于m-1,需要将前(m-1)/2作为左子树,第m/2个记录作为父节点的值,m/2及其后面的记录作为右子树。

在这里插入图片描述

插入17:

在这里插入图片描述

插入18

在这里插入图片描述

调整元素位置:

在这里插入图片描述

添加数据直到下图:

在这里插入图片描述

现在添加7:节点记录大于m-1
在这里插入图片描述

进行分裂:

在这里插入图片描述

此时父节点记录个数大于m-1,执行第三步:需要将前(m-1)/2作为左子树,第m/2个记录作为父节点的值,m/2以后的记录作为右子树。

在这里插入图片描述

非叶子节点也称为内部节点,表示索引,并且它左子树都小于它,它的右子树都大于它。

删除操作

  1. 删除叶子结点中对应的值。删除后若结点的值的个数大于等于Math.ceil(m-1)/2 – 1,删除操作结束,否则执行第2步。
  2. 若兄弟结点值有富余(大于Math.ceil(m-1)/2 – 1),向兄弟结点借一个记录,同时用借到的值替换父结(指当前结点和兄弟结点共同的父结点)点中的值,删除结束。否则执行第3步。
  3. 若兄弟结点中没有富余的记录,则当前结点和兄弟结点合并成一个新的叶子结点,并删除父结点中的记录(父结点中的这个记录两边的孩子指针就变成了一个指针,正好指向这个新的叶子结点),将当前结点指向父结点(必为索引结点),执行第4步(第4步以后的操作和B树就完全一样了,主要是为了更新索引结点)。
  4. 若索引结点的记录的个数大于等于Math.ceil(m-1)/2 – 1,则删除操作结束。否则执行第5步
  5. 若兄弟结点有富余,父结点记录下移,兄弟结点记录上移,删除结束。否则执行第6步
  6. 当前结点和兄弟结点及父结点下移记录合并成一个新的结点。将当前结点指向父结点,重复第4步。

注意,通过B+树的删除操作后,索引结点中存在的key,不一定在叶子结点中存在对应的记录。也就是在删除时如果叶子结点中没有相应的key,则删除失败。

初始值:

在这里插入图片描述

删除22:根据步骤一,删除后节点值个数大于等于Math.ceil(m-1)/2 – 1,删除结束。

在这里插入图片描述

删除15:删除后的节点值个数小于Math.ceil(m-1)/2 – 1,执行第二步。

在这里插入图片描述

兄弟结点值有富余(大于Math.ceil(m-1)/2 – 1),向兄弟结点借一个记录,同时用借到的值替换父结(指当前结点和兄弟结点共同的父结点)点中的值。可以从兄弟结点借一个关键字为9的记录,同时更新将父结点中的关键字由10也变为9,删除结束。

在这里插入图片描述

删除7:删除7之后当前节点只有一个记录,小于Math.ceil(m-1)/2 – 1。而兄弟节点也都不能提供借出,只能将它与一个兄弟节点合并。

在这里插入图片描述

执行第四步:合并完成后,父节点记录个数小于Math.ceil(m-1)/2 – 1。兄弟节点也没有多余的记录可以借,那就合并。

在这里插入图片描述

执行第六步:

在这里插入图片描述

B树和B+树的区别?

B树和B+树主要有两个区别:

  • B树的叶子节点和非叶子节点都可以存放键和值,B+树所有数据存储在叶子节点,非叶子节点只存放键。
  • B+树的叶子节点是联通的,方便顺序检索。

MySQL数据库为啥用B+树作为索引,而不用B树?

  • B+树可以随机查询也可以顺序查询,而B树只能随机查询。
  • B+树更加节省空间。B树每个节点都存储键和值,而B+树的内部节点只存储键,这样一个节点就可以存储更多的索引,使得树的高度变低,提高了IO的效率。
  • B+树的叶子节点是链接的,可以方便范围查找和顺序查找。
  • B+树的性能更加稳定,每次查询都是从根节点到叶子,而B树可能在内部某个节点就已经找到查找到了。

什么时候使用B树合适呢?因为B树在内部节点也会存储值,所以将一些热点访问数据放在距离根节点进的地方,可以提高数据访问效率。综上所说B+树更适合作为索引的结构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/104007.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

变色树脂T-46CC详解

一、产品介绍 Tulsimer T-46 CC 是一款专门研制的、优质的、强酸型的聚苯乙烯架构的阳离子交换树脂,具有核子级磺酸官能团, 并同时拥有绝佳的物理及化学稳定品质,因此广泛应用于水处理当中。 Tulsimer T-46 CC 主要用于水净化处理&#xff…

智慧党建VR虚拟3D数字化展厅发展和传承传统文化

三维全景虚拟现实技术应用在虚拟展馆中,主要是通过全景照片的虚拟与建模,营造出三维虚拟仿真的场景,从而结合展馆展示的需求,营造出更加有效的氛围,起到优化展示效果的作用。 三维全景虚拟现实技术的应用,能…

Java【手撕双指针】LeetCode 611. “有效三角形个数“, 图文详解思路分析 + 代码

文章目录 前言一、有效三角形个数1, 题目2, 思路分析1, 从左往右 or 从右往左?3, 代码展示 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: 📕 JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等 &#x1…

BootstrapBlazor组件使用:数据注解

文章目录 前言BB数据注解数据注解源码数据注解简介注解简单实例[BB 编辑弹窗](https://www.blazor.zone/edit-dialog)[ValidateForm 表单组件](https://www.blazor.zone/validate-form)使用简介 前言 BootstrapBlazor(一下简称BB)是个特别好用的组件,基本上满足了大…

jupyter notebook出现ERR_SSL_VERSION_OR_CIPHER_MISMATCH解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

软件测试架构师在实际工作中都做哪些事情呢?

软件测试架构师在实际工作中,都做哪些事情呢? 一家业务体系庞大、复杂的公司的测试架构师的职责主要有五个: 1、测试团队的技术带头人 测试架构师会关注整个团队的技术提升,包括技术难题的攻关,团队遇到的技术难题&…

(6)(6.3) 自动任务中的相机控制

文章目录 前言 6.3.1 概述 6.3.2 自动任务类型 6.3.3 创建合成图像 前言 本文介绍 ArduPilot 的相机和云台命令,并说明如何在 Mission Planner 中使用这些命令来定义相机勘测任务。这些说明假定已经连接并配置了相机触发器和云台(camera trigger and gimbal ha…

ORB-SLAM2报错集合(数据集测试系列1)

目录 错误1 错误2 错误3 错误4 错误5 错误6 错误7 错误8 TUM-RGBD测试 KITTI测试 EuRoC测试 写在前面~ ORB-SLAM2 github链接:GitHub - electech6/ORB_SLAM2_detailed_comments: Detailed comments for ORB-SLAM2 with trouble-shooting, key formula …

QChart:数据可视化(用图像形式显示数据内容)

1、数据可视化的图形有:柱状/线状/条形/面积/饼/点图、仪表盘、走势图,弦图、金字塔、预测曲线图、关系图、数学公式图、行政地图、GIS地图等。 2、在QT Creator的主页面,点击 欢迎》示例》右侧输入框 输入Chart,即可查看到QChar…

回归预测 | MATLAB实现SSA-RF麻雀搜索优化算法优化随机森林算法多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现SSA-RF麻雀搜索优化算法优化随机森林算法多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现SSA-RF麻雀搜索优化算法优化随机森林算法多输入单输出回归预测(多指标,多图)…

数据结构—排序

8.排序 8.1排序的概念 什么是排序? 排序:将一组杂乱无章的数据按一定规律顺序排列起来。即,将无序序列排成一个有序序列(由小到大或由大到小)的运算。 如果参加排序的数据结点包含多个数据域,那么排序往…

Ubuntu18.04 交叉编译curl-7.61.0

下载 官方网址是:curl 安装依赖库 如果需要curl支持https协议,需要先交叉编译 openssl,编译流程如下: Ubuntu18.04 交叉编译openssl-1.1.1_我是谁??的博客-CSDN博客 解压 # 解压: $tar -xzvf curl-7.61.…

【Go】Goland项目配置运行教程

Golang项目配置运行教程 1.安装Golang下载安装包安装 2.Goland配置2.1 环境2.2 goland配置2.2.1 没有makefile的情况2.2.2 有makefile的情况 3.跨平台项目4.补充 注意,本项目描述的是git clone下来的Golang项目配置运行教程,并不是从头创建一个Golang项目…

redis常用五种数据类型详解

目录 前言: string 相关命令 内部编码 应用场景 hash 相关命令 内部编码 应用场景 list 相关命令 内部编码 应用场景 set 相关命令 内部编码 应用场景 Zset 相关命令 内部编码 应用场景 渐进式遍历 前言: redis有多种数据类型&…

Cookie 和 Session 的工作流程

目录 一、Cookie是什么? 二、Session是什么? 三、Cookie的工作流程 四、Session的工作流程 五、Session和Cookie的区别和联系 一、Cookie是什么? Cookie是一种在网站和用户之间交换信息的机制。它是由Web服务器发送给用户浏览器的小型文本文件&#xff…

【leetcode 力扣刷题】反转链表+递归求解

反转链表递归求解 206. 反转链表解法①:取下一个节点在当前头节点前插入解法②:反转每个节点next的指向解法③:递归 92.反转链表Ⅱ反转left到right间节点的next指向 234.回文链表解法①:将链表元素存在数组中,在数组上…

解决idea登录github copilot报错问题

试了好多方案都没用,但是这个有用, 打开idea-help-edit custonm vm options 然后在这个文件里面输入 -Dcopilot.agent.disabledtrue再打开 https://github.com/settings/copilot 把这个设置成allow,然后重新尝试登录copilot就行就行 解决方…

【JVM 内存结构 | 程序计数器】

内存结构 前言简介程序计数器定义作用特点示例应用场景 主页传送门:📀 传送 前言 Java 虚拟机的内存空间由 堆、栈、方法区、程序计数器和本地方法栈五部分组成。 简介 JVM(Java Virtual Machine)内存结构包括以下几个部分&#…

countDown+react+hook

道阻且长,行而不辍,未来可期 知识点一: new Date().getTime()可以得到得到1970年01月1日0点零分以来的毫秒数。单位是毫秒 new Date().getTime()/1000获取秒数1分钟60秒,1小时60分钟1hour:60*60>单位是秒 60*60*1000>单位…

Android 9.0 Vold挂载流程解析(下)

Android 9.0 Vold挂载流程解析(上) 前言 上一篇介绍了Android 文件系统中Vold挂载机制的总体框架,我们分析了vod进程的main.cpp.接下来我们分析下存储卡挂载和卸载的流程。 存储卡挂载 在上篇文章文章提到,监听驱动层挂载和卸…