【C++从0到王者】第五十一站:B+树

文章目录

  • 一、B+树
    • 1.B+树的概念
    • 2.B+树的特性
    • 3.B+树的插入的过程
    • 4.总结
  • 二、B*树
    • 1. B*树的概念
    • 2.B*树的分裂
  • 三、总结
  • 四、B树系列和哈希和平衡搜索树作对比
  • 五、B树的一些应用
    • 1.索引
    • 2.MySQL索引
    • 3.MyISAM
    • 2.InnoDB

一、B+树

1.B+树的概念

B+树是B树的变形,是在B树基础上优化的多路平衡搜索树,B+树的规则跟B树基本类似,但是又在B树的基础上做了以下几点改进优化:

  1. 分支节点的子树指针与关键字个数相同

  2. 分支节点的子树指针p[i]指向关键字值大小在[k[i],k[i+1])区间之间。(相当于取消了最左边的那棵树

  3. 所有叶子节点增加一个链接指针链接在一起

  4. 所有关键字及其映射数据都在叶子节点出现 (分支结点跟叶子结点有重复的值,分支结点存的是叶子结点的索引。父亲中存的是孩子结点中的最小值做索引

image-20240226132011255

2.B+树的特性

B+树的特性:

  1. 所有关键字都出现在叶子节点的链表中,且链表中的节点都是有序的。
  2. 不可能在分支节点中命中。
  3. 分支节点相当于是叶子节点的索引,叶子节点才是存储数据的数据层

3.B+树的插入的过程

如下是M=3时候的B+树的插入分裂过程

image-20240226133712278

image-20240226133721283

B+树的插入过程根B树是类似的,细节区别在于,第一次插入两层,一层结点做分支,一层做根

后面一样都是往叶子中去插入的,插入满了以后,分裂一半给兄弟,转换成往父亲插入一个key和一个孩子,孩子就是兄弟,key是兄弟的第一个最小的key。

B+树的分裂:
当一个结点满时,分配一个新的结点,并将原结点中1/2的数据复制到新结点,最后在父结点中增加新结点的指针;B+树的分裂只影响原结点和父结点,而不会影响兄弟结点,所以它不需要指向兄弟的指针。

4.总结

  • 简化了B树孩子比关键字多一个的规则,变成了相等
  • 所有的值都在叶子上,方便遍历查找所有的值

二、B*树

1. B*树的概念

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

image-20240226135012980

2.B*树的分裂

B+树的分裂:
当一个结点满时,分配一个新的结点,并将原结点中1/2的数据复制到新结点,最后在父结点中增加新结点的指针;B+树的分裂只影响原结点和父结点,而不会影响兄弟结点,所以它不需要指向兄弟的指针。

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

B*的结点的关键字和和孩子数量是在[2/3*M, M]之间的

image-20240226135118261

三、总结

大致将B树,B+树,B*树总结如下:
B树:有序数组+平衡多叉树;
B+树:有序数组链表+平衡多叉树;
B*树:一棵更丰满的,空间利用率更高的B+树。

四、B树系列和哈希和平衡搜索树作对比

在内存中作内查找时候

单纯论树的高度,搜索效率,B树确实不错

但是B树系列也有一些隐形坏处

  1. 空间利用率低,消耗高

  2. 插入删除数据时,分裂和合并节点,那么必然挪动数据

  3. 虽然高度更低,但是在内存中而言,与哈希和平衡搜索树还是一个量级中。

比如当M为1024的时候,N为10亿的时候

B树的次数为3次,而平衡树的效率为30次

在内存中搜索3次和30次差别不是特别大

但是在磁盘中搜索3次和30次差别巨大

结论:实质上B树系列在内存中体现不出优势

五、B树的一些应用

1.索引

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

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

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

像我们在使用B+树去索引磁盘数据的时候,分支结点只存储key值,这就可以使得分支结点比较小。分支结点映射的磁盘数据块就可以尽量加载到Cache中,从而提高效率

image-20240226165355350

2.MySQL索引

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

image-20240226162257642

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

注意:索引是基于表的,而不是基于数据库的

3.MyISAM

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

image-20240226170156153

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

image-20240226170249922

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

我们也可以用name来进行索引。image-20240226170501566

  • 一般数据库要求主键是唯一的,比如mysql建表的主键,就是B+s树的key。B+树的value是存储一行数据的磁盘地址

  • 分支节点也是需要存盘中的,因为数据量大了,内存是存不下的,分支结点中应该是磁盘地址。

  • 但是分支结点理论上应该被尽量缓存到cache

  • image-20240226174729476

  • 一般数据库要求主键值是不重复唯一字段,比如电话、身份证号码适合,但是名字,地址不适合

没有字段能保持唯一,可以考虑自增主键(其实它自己建立一个自增整数做完主键)

一般数据库不要求索引唯一,像mysql建立索引可以考虑使用B+树或者Hash表,数据结构允许冗余

像下面的语句中,插入第二条语句就会报错,因为主键张伟已经存在了。

image-20240226175716406

B+树做主键索引相比B树的优势如下:

  1. B+树所有值都在叶子,遍历很方便,方便区间查找
  2. 对于没有建立索引的字段,全表扫描的遍历很方便
  3. 分支结点值存储key,一个分支结点空间占用更小,可以尽可能加载到缓存

B树不用叶子就能找到值,B+树一定要到叶子,这是B树一个优势,但是B+树高度足够低,所以差别不大

image-20240226180247747

2.InnoDB

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

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

image-20240226180529403

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

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

image-20240226180624216

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

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

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

相关文章

Java网络爬虫实践:解析微信公众号页面的技巧

在当今数字化时代,信息获取已经成为了一项至关重要的任务。然而,随着信息量的爆炸性增长,人工处理这些信息已经变得不太现实。这时候,网络爬虫就成为了一种强大的工具,能够帮助我们从海量的网页中快速准确地获取所需信…

【软件测试】上岗第一天,组长就要我做自动化测试?我该咋办?

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 如果你恰好刚刚进…

如何在Linux系统Docker部署Dashy并远程访问内网服务界面

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Cesium-记录差值线

/*** param {Object} startTime Date格式的开始时间* param {Object} endTime Date格式的结束时间* param {Object} coordinates [x1,y1,x2,y2,x3,y3.......]* param {Object} entityCollection 实体收集器*/ async function interpolationLine(startTime,endTime,coordinat…

git log查看项目中各成员的代码提交情况,行数,次数等

前言: 项目中通过git来提交代码后,可以通过git log的不同命令来查看项目中各成员的代码提交情况,行数,次数。 具体操作: 1、查看所有的提交日志,回车查看更多,不过太多会卡死,需要重新开 git …

神经网络(neural network)

在这一章中我们将进入深度学习算法,学习一些神经网络相关的知识,这些是有更加强大的作用,更加广泛的用途。 神经元和大脑(neurons and the brain): 我们对于我们的编程的进步主要来自我们对于大脑的研究,根据我们对于大脑的研究…

【中间件】docker的安装

📝个人主页:五敷有你 🔥系列专栏:中间件 ⛺️稳中求进,晒太阳 .卸载旧版 首先如果系统中已经存在旧的Docker,则先卸载: yum remove docker \docker-client \docker-client-latest \doc…

【C++】string类的基础操作

💗个人主页💗 ⭐个人专栏——C学习⭐ 💫点击关注🤩一起学习C语言💯💫 目录 导读 1. 基本概述 2. string类对象的常见构造 3. string类对象的容量操作 4. string类对象的访问及遍历操作 5. 迭代器 6.…

javaWebssh教师荣誉库管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh在线授课辅导系统是一套完善的web设计系统(系统采用ssh框架进行设计开发),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0…

【DP】蓝桥杯第十三届-费用报销

#include<iostream> #include<algorithm> #include<cstring> #include<set> #include<queue> using namespace std; const int N1010; int dp[N][5010];//dp[i][j]:选到第i个物品是否能取到价值j&#xff1b; int month[13]{0,31,28,31,30,31,30…

代码随想录day15(2)栈与队列:滑动窗口最大值(leetcode239)

题目要求&#xff1a;给定一个数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。 思路&#xff1a;首先的想法就是暴力方法&#xff0c;遍历一遍…

专访|云安全攻防:从理论到应用的全面探索

2023年11月&#xff0c;美国核研究实验室&#xff08;INL&#xff09;遭遇数据泄露。同年10月&#xff0c;索尼的员工数据在MOVEit攻击事件中被泄露。2024年2月&#xff0c;某知名制造商因云存储服务器的配置错误导致了敏感数据泄露。 这些事件表示企业必须重视云安全建设&…

第一套试卷大题

1.邻接矩阵和邻接表的写法&#xff1a; **介绍&#xff1a;**该图是一个无向图&#xff0c;所以邻接矩阵一定是对称的&#xff0c;而邻接表某节点的边数为无向图某节点的连接数 无向图的邻接矩阵&#xff1a; 无向图的邻接表&#xff08;不唯一&#xff09;&#xff1a; 根据无…

快速排序hoare优化

目录 三数取中法选key 优化点 基本思想 代码实现 小区间优化 优化点 基本思想 代码实现 由于hoare版快排在一些特殊情况下性能并不优&#xff0c;这里我们进行一些优化。 三数取中法选key 优化点 当数据有序时&#xff0c;快排就会很吃力&#xff0c;这是为什么呢…

[C语言]——分支和循环(1)

目录 一.if语句 1.if 2.else 3.分支中包含多条语句 4.嵌套if 5.悬空else问题 二.关系操作符 三.条件操作符 C语⾔是结构化的程序设计语⾔&#xff0c;这⾥的结构指的是顺序结构、选择结构、循环结构&#xff0c;C语⾔是能够实现这三种结构的&#xff0c;其实我们如果仔细分析&a…

【深度学习笔记】优化算法——梯度下降

梯度下降 &#x1f3f7;sec_gd 尽管梯度下降&#xff08;gradient descent&#xff09;很少直接用于深度学习&#xff0c; 但了解它是理解下一节随机梯度下降算法的关键。 例如&#xff0c;由于学习率过大&#xff0c;优化问题可能会发散&#xff0c;这种现象早已在梯度下降中…

博客系统测试

文章目录 1.项目背景介绍2.功能介绍3.手动测试3.1编写测试用例3.2项目测试3.2.1登录测试3.2.2查看详情页面3.2.3编辑页面3.2.4删除博客3.2.5注销用户 大家好&#xff0c;我是晓星航。今天为大家带来的是 博客系统测试 相关的讲解&#xff01;&#x1f600; 1.项目背景介绍 项…

探讨倒排索引Elasticsearch面试与实战:从理论到实践

在当前大数据时代&#xff0c;Elasticsearch&#xff08;以下简称为ES&#xff09;作为一种强大的搜索和分析引擎&#xff0c;受到了越来越多企业的青睐。因此&#xff0c;对于工程师来说&#xff0c;掌握ES的面试准备和实战经验成为了必备技能之一。本文将从ES的面试准备和实际…

KL散度和交叉熵的应用介绍

深度学习 文章目录 深度学习前言KL散度和交叉熵KL散度与交叉熵的关系KL散度与交叉熵的应用总结 前言 KL散度&#xff08;Kullback-Leibler Divergence&#xff09;和交叉熵&#xff08;Cross Entropy&#xff09;是在机器学习中广泛使用的概念。这两者都用于比较两个概率分布之…

day14_异常

今日内容 零、 复习昨日 一、日期类 二、异常 零、 复习昨日 1为什么要重写toString Object类toString返回的是对象名字地址,无意义子类重写toString() 返回的对象属性内容 2为什么要重写equals Object类equals判断是对象的地址值是否相等,无意义子类重写equals,为了判断对象的…