当前位置: 首页 > news >正文

【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

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

相关文章:

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

文章目录 一、B树1.B树的概念2.B树的特性3.B树的插入的过程4.总结 二、B*树1. B*树的概念2.B*树的分裂 三、总结四、B树系列和哈希和平衡搜索树作对比五、B树的一些应用1.索引2.MySQL索引3.MyISAM2.InnoDB 一、B树 1.B树的概念 B树是B树的变形,是在B树基础上优化的…...

Spring Cloud 面试题及答案整理,最新面试题

Spring Cloud中断路器的原理及其作用是什么? Spring Cloud断路器的原理和作用基于以下几个关键点: 1、故障隔离机制: 在微服务架构中,断路器作为一种故障隔离机制,当某个服务实例出现问题时,断路器会“断…...

使用Kali搭建钓鱼网站教程

一、前言 使用kali工具一分钟制作出和目标网站一模一样的钓鱼网站。目标用户使用钓鱼网站登录自己的账号,账号密码将被自动劫持。 二、钓鱼网站的制作过程 1.在虚拟机VMvare中登录kali linux 2.准备一个目标网址 3.在kail中搜索使用工具 4.在弹出的选项中选择第一…...

《TCP/IP详解 卷一》第15章 TCP数据流与窗口管理

目录 15.1 引言 15.2 交互式通信 15.3 延时确认 15.4 Nagle 算法 15.4.1 延时ACK与Nagle算法结合 15.4.2 禁用Nagle算法 15.5 流量控制与窗口管理 15.5.1 滑动窗口 15.5.2 零窗口与TCP持续计时器 15.5.3 糊涂窗口综合征 15.5.4 大容量缓存与自动调优 15.6 紧急机制…...

ContentType类型总结

ContentType类型总结 Content-Type是一个HTTP头部字段,用于指示资源的媒体类型(MIME类型),以及可选的字符集和编码方式。它告诉浏览器或其他客户端如何解释接收到的数据。以下是一些常见的Content-Type类型及其用途: t…...

基于脚手架创建vue工程

环境要求: node.js:前端项目的运行环境 npm:javascript的包管理器 vue cli:项目脚手架 忘了自己有没有安装可以通过在黑窗口输入命令看一下 node -v npm -v 这里出现版本号就说明已经安装了 安装脚手架的命令:npm i vue/cli -g 创建vue基础工程 1.在一个没…...

【Http】OSI 和 TCP/IP,OSI,TCP/IP为什么网络要分层?

目录 OSI 和 TCP/IP OSI TCP/IP 为什么网络要分层? OSI 和 TCP/IP OSI ![image-20231205101106040](.assets/image-20231205101106040.pn OSI 的七层体系结构概念清楚,理论也很完整,但是它比较复杂而且不实用,而且有些功能在…...

STM32(5) GPIO(2)输出

1.点亮LED 1.1 推挽接法和开漏接法 要想点亮LED,有两种接法 推挽接法: 向寄存器写1,引脚输出高电平,LED点亮;向寄存器写0,引脚输出低电平,LED熄灭。 开漏接法: 向寄存器写0&…...

shell脚本一键部署docker

Docker介绍 Docker 是一个开源的平台,用于开发、交付和运行应用程序。它利用容器化技术,可以帮助开发人员更轻松地打包应用程序及其依赖项,并将其部署到任何环境中,无论是开发工作站、数据中心还是云中。以下是 Docker 的一些关键…...

vue2实现拖拽排序效果

1、首先下载 vuedraggable 插件 npm i -S vuedraggable2、使用方法 <template><div><div style"display: flex; justify-content: center; align-items: center"><div style"width: 120px; height: 60px; line-height: 60px; text-align…...

数据结构实验:二叉排序树

题目描述 对应给定的一个序列可以唯一确定一棵二叉排序树。然而&#xff0c;一棵给定的二叉排序树却可以由多种不同的序列得到。例如分别按照序列{3,1,4}和{3,4,1}插入初始为空的二叉排序树&#xff0c;都得到一样的结果。你的任务书对于输入的各种序列&#xff0c;判断它们是否…...

Java类加载流程?

Java类加载过程是指将.class文件中的字节码数据加载到内存中&#xff0c;并生成对应的Class对象的过程。Java类加载器&#xff08;ClassLoader&#xff09;负责执行这个任务。Java类加载过程主要包括以下几个步骤&#xff1a; 加载&#xff08;Loading&#xff09;&#xff1a;…...

Docker从0到1的开始【入门篇】

Docker是一种流行的容器化平台&#xff0c;它允许开发人员将应用程序及其所有依赖项打包到一个标准化的单元中&#xff0c;从而实现快速部署和可移植性。在本文中&#xff0c;我们将列出一些常用的Docker命令&#xff0c;以帮助您更好地了解和使用Docker。 1. 安装Docker 要安…...

@ResponseStatus

目录 概述&#xff1a; 用途&#xff1a; 参数&#xff1a; 注意事项&#xff1a; 自定义异常类&#xff1a; 底层原理&#xff1a; 概述&#xff1a; 在 Spring MVC 中&#xff0c;我们有很多方法来设置 HTTP 响应的状态码其中最直接的方法&#xff1a;使用 ResponseSt…...

高效加载大文件(pandas+dask)

一、仅用pd加载大文件(iterator、chunksize) 要使用Pandas进行高效加载超大文件&#xff0c;我们通常会利用其内置的分块&#xff08;chunk&#xff09;处理功能。不过&#xff0c;请注意&#xff0c;Pandas本身并不支持多线程读取文件&#xff1b;它更倾向于单线程中进行块处理…...

游戏引擎分层简介

游戏引擎分层架构&#xff08;自上而下&#xff09; 工具层&#xff08;Tool Layer&#xff09; 在一个现代游戏引擎中&#xff0c;我们最先看到的可能不是复杂的代码&#xff0c;而是各种各样的编辑器&#xff0c;利用这些编辑器&#xff0c;我们可以制作设计关卡、角色、动画…...

向爬虫而生---Redis 探究篇6<Redis的Bigkey问题介绍>

前言: 随着数据规模的增长,Redis的BigKey问题也开始显现。 BigKey问题主要指的是存储了大量数据的key,这可能给Redis的性能和可用性带来负面影响。当一个key的数据量过大时,会占用宝贵的内存资源,拖慢Redis的响应速度。此外,存储和恢复这些BigKey也会变得困难和耗时,增…...

【开源物联网平台】FastBee认证方式和MQTT主题设计

&#x1f308; 个人主页&#xff1a;帐篷Li &#x1f525; 系列专栏&#xff1a;FastBee物联网开源项目 &#x1f4aa;&#x1f3fb; 专注于简单&#xff0c;易用&#xff0c;可拓展&#xff0c;低成本商业化的AIOT物联网解决方案 目录 一、接入步骤 1.1 设备认证 1.2 设备交…...

Ubuntu Qt控制终端运行ros

文章目录 gnome-terminalQt 通过QProcess类Qt 通过system gnome-terminal 在Ubuntu中可以使用man gnome-terminal命令查看gnome-terminal的使用指南&#xff0c;也可在ubuntu manuals查看&#xff1a; NAMEgnome-terminal — 一个终端仿真应用.概要gnome-terminal [-e, --c…...

mysql 性能调优参数配置文件

########################################################################### ## my.cnf for MySQL 8.0.x # ## 本配置参考 https://imysql.com/my-cnf-wizard.html # ## 注意&#xff1a; …...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

前端高频面试题2:浏览器/计算机网络

本专栏相关链接 前端高频面试题1&#xff1a;HTML/CSS 前端高频面试题2&#xff1a;浏览器/计算机网络 前端高频面试题3&#xff1a;JavaScript 1.什么是强缓存、协商缓存&#xff1f; 强缓存&#xff1a; 当浏览器请求资源时&#xff0c;首先检查本地缓存是否命中。如果命…...