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+树更适合作为索引的结构。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

NLP序列标注问题,样本不均衡怎么解决?

【学而不思则罔,思而不学则殆】 1.问题 NLP序列标注问题,样本不均衡怎么解决? 2.解释 以命名实体识别(NER)为例,这个样本不均衡有两种解释: (1)实体间类别数量不均衡…

关于vant2 组件van-dropdown-item,在IOS手机上,特定条件下无法点击问题的探讨

情景重现 先贴有问题的代码 <template><div :class"showBar ? homeContain : homeContain-nobar"><div class"contant" id"content"><van-dialog v-model"loading" :before-close"onBeforeClose" :…

【Python从入门到进阶】32、bs4的基本使用

接上篇《31、使用JsonPath解析淘票票网站地区接口数据》 上一篇我们介绍了如何使用JSONPath来解析淘票票网站的地区接口数据&#xff0c;本篇我们来学习BeautifulSoup的基本概念&#xff0c;以及bs4的基本使用。 一、BeautifulSoup简介 1、bs4基本概念 BeautifulSoup是一个P…

.Net Core 动态加载和卸载程序集

从 .Net Core 3.0开始支持程序集的加载和卸载&#xff0c;在 .Net FrameWork中使用独立的应用程序域来实现同样的功能&#xff0c;.Net Core 不支持创建多个应用程序域&#xff0c;所以无法使用多个应用程序域来实现程序集动态加载和卸载。 AssemblyLoadContext 程序集加载上下…

使用pnpm workspace管理Monorepo架构

在开发项目的过程中&#xff0c;我们需要在一个仓库中管理多个项目&#xff0c;每个项目有独立的依赖、脚手架&#xff0c;这种形式的项目结构我们称之为Monorepo&#xff0c;pnpm workspace就是管理这类项目的方案之一。 一、pnpm简介 1、pnpm概述 pnpm代表performance npm…

Docker容器:docker基础概述、安装、网络及资源控制

文章目录 一.docker容器概述1.什么是容器2. docker与虚拟机的区别2.1 docker虚拟化产品有哪些及其对比2.2 Docker与虚拟机的区别 3.Docker容器的使用场景4.Docker容器的优点5.Docker 的底层运行原理6.namespace的六项隔离7.Docker核心概念 二.Docker安装 及管理1.安装 Docker1.…

525. 连续数组

525. 连续数组 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a; 原题链接&#xff1a; 525. 连续数组 https://leetcode.cn/problems/contiguous-array/description/ 完成情况&#xff1a; 解题思路&#xff1a; 参考代码&#xff1a; …

初出茅庐的小李博客之STM32CubeMx配置定时器的编码器模式

STM32CubeMx配置定时器的编码器模式 上次文章写了编码器是如何工作的&#xff0c;今天就来用STM32F103C8T6的TIM3的通道1跟通道2编写一个编码器识别程序。 编程思路&#xff1a; A相:TIM3_CH1 B相:TIM3_CH2 SWITCH:PB5&#xff08;外部中断的方式&#xff09; 实现效果&a…

基于Java/springboot铁路物流数据平台的设计与实现

摘要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;铁路物流数据平台当然也不能排除在外&#xff0c;从文档信息、铁路设计的统计和分析&#xff0c;在过程中会产生大量的、各…

基于SpringCloud的会议室预约系统Java基于微服务的会议室报修系统【源码+lw】

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人七年开发经验&#xff0c;擅长Java、微信小程序、Python、Android、大数据等&#xff0c;大家有这一块的问题可以一起交流&#xff01; &#x1f495;&#x1f495…

Docker入门——实战图像分类

一、背景 思考&#xff1a; 在一个项目的部署阶段&#xff0c;往往需要部署到云服务器或者是终端设备上&#xff0c;而环境的搭建往往是最费时间和精力的&#xff0c;特别是需要保证运行环境一致性&#xff0c;有什么办法可以批量部署相同环境呢&#xff1f; Docker本质——…

Django模型基础

文章目录 一、models字段类型概述属性命名限制使用方式逻辑删除和物理删除常用字段类型 二、常用字段参数常用字段选项(通过字段选项&#xff0c;可以实现对字段的约束) 实践创建模型执行迁移命令 并 创建超级用户登录admin后台添加文件和图片字段定义模型字段和约束及在Admin后…

vscode如何汉化

首先我们到vscode官网下载 链接如下&#xff1a; Visual Studio Code - Code Editing. Redefined 根据自己需要的版本下载就好 下载并且安装完毕之后 运行vscode 然后按快捷键 CTRLSHIFTX 打开安装扩展界面 搜索简体中文 安装就可以了 谢谢大家观看

聊聊看React和Vue的区别

Vue 更适合小项目&#xff0c;React 更适合大公司大项目&#xff1b; Vue 的学习成本较低&#xff0c;很容易上手&#xff0c;但项目质量不能保证...... 真的是这样吗&#xff1f;借助本篇文章&#xff0c;我们来从一些方面的比较来客观的去看这个问题。 论文档的丰富性 从两个…

kubesphere 集成 sonar

文章目录 安装 helm通过 helm 安装 sonar配置 SonarQube 服务器创建 SonarQube 管理员令牌SonarQube 配置添加到 ks-installer创建 Webhook 服务器将 SonarQube 服务器添加至 Jenkins将 sonarqubeURL 添加到 KubeSphere 控制台重启服务 为新项目创建 SonarQube Token 官方文档&…

Hlang--用Python写个编程语言-函数与基本数据结构实现

文章目录 前言语法表述解析器修改词法解析函数节点函数节点解析List的解析实现解释器节点函数操作String和List处理总结前言 okey,经过一段时间的努力,接下来要实现的是函数。当然还有对应的基本数据结构,那么之后的话,我们的工作就开始进一步转换了。 那么在这块我们要实…

绘制原型图的常用工具之墨刀

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于OA项目的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.墨刀是什么 二.墨刀的作用 三.墨刀界…

【ES6】—使用 const 声明

一、不属于顶层对象window 使用const关键字 声明的变量&#xff0c;不会挂载到window属性上 const a 5 console.log(a) console.log(window.a) // 5 // undefined二、不允许重复声明 使用const关键字不允许重复声明相同的变量 cosnt a 5 cosnt a 6 // Uncaught SyntaxEr…

自然语言处理技术:NLP句法解析树与可视化方法

自然语言处理(Natural Language Processing,NLP)句法解析树是一种表示自然语言句子结构的图形化方式。它帮助将句子中的每个词汇和短语按照语法规则连接起来,形成一个树状结构,以便更好地理解句子的语法结构和含义。句法解析树对于理解句子的句法关系、依存关系以及语义角…

【Android Framework系列】第11章 LayoutInflater源码分析

1 前言 本章节我们主要目目的是了解Activity的xml布局解析、对LayoutInfater源码进行分析。 我们知道Android界面上的每一个控件都是一个个View&#xff0c;但是Android也提供了通过xml文件来进行布局控制&#xff0c;那么xml布局文件如何转成最终的View的呢&#xff1f;转换利…