了解数据库中常用存储引擎数据结构(2)

news2024/9/20 22:51:42

目录

深入了解B树及其变种

BTree

B+Tree

B*Tree

BTree并发机制


深入了解B树及其变种

先把我们要解释的B树变种都列出来,B树的变种主要有B+树、B*树、B-Link树、COW B树、惰性B树、Bw树等。

下面具体来分析这些变种的优势和发展趋势。

BTree

下图是原始 BTree 的结构,

可以注意到:在 BTree 中,每个数据只存储一份。

如果要进行全表扫描,则需要中序遍历整个 BTree,因此会产生大量的随机 IO,性能不佳。所以基本上没有直接使用 BTree 实现存储结构的。

BTree 早期有两个变种:

  • B+Tree
  • B*Tree

B+Tree

相比于 BTree,B+Tree 的数据按照键值大小顺序存放在同一层的叶子节点中(和上面 BTree 中在非叶子节点也存放数据不同),各个叶子节点按照指针连接,组成一个双向链表。

因此,对于 B+Tree 而言,其非叶子节点仅仅作为查找路径的判断依据,一个 key 值可能在 B+Tree 中存在两份(仅 Key 值)。

B+Tree 的结构解决了 BTree 中中序遍历扫描的痛点,在一定程度上也能降低层数。

B*Tree

B*Tree 是 BTree 的另一个变种,其最关键的一点是将节点的最低空间利用率从 BTree 和 B+Tree 的 1/2 提高到了 2/3,并由此改变了节点数据满时的处理逻辑。

我们知道,BTree 和 B+Tree 的空间利用率为 1/2,即:们的叶子节点满而分裂时,默认状态下会分裂为两个各占一半数据的节点;

而 B*Tree在一个节点满了却又有新的数据要插入进来时,它会将其部分数据搬迁到下一个兄弟节点,直到两个节点空间都满了,就在中间生成一个节点,三个节点平分原来两个节点中的数据。

B*Tree 的思想主要是:将当前节点和兄弟节点相关联。

B*Tree 的这种设计虽然可以提升空间利用率,对减少层数、提升读性能有一定的帮助,但这种模式增加了写入操作的复制度;

而且向右兄弟节点搬迁数据的过程也要视作为一种 SMO 操作,对写入和并发能力有极大的损耗!因此,B*Tree 并没有被大量使用。

BTree并发机制

这里以 MySQL InnoDB 存储引擎为例,讲述基于 B+Tree 的存储引擎是如何通过 Latch 进行并发控制的。

在 MySQL 5.6 之前的版本,只有写和读两种 Latch,被称为 X Latch 和 S Latch。

对于读的过程,

  • 首先要在整个索引上添加 Index S Latch。
  • 再从上至下找到要读的叶子节点的 Page,然后上叶子节点的 Page S Latch。
  • 这时就可以释放 Index S Latch了。
  • 然后进行查询并返回结果,最后释放叶子节点中的 Page S Latch,完成整个读操作。

对于写的过程,

  • 首先进行乐观的写入,即:假设写入操作不会引起索引结构的变更(不触发 SMO 操作)。
    • 要先上整个索引的 Index S Latch,再从上至下找到要修改的叶子节点的 Page,此过程和上面的读取步骤相同!
    • 接下来判断叶子节点是否安全,即:写入操作是否会触发分裂或者合并;
    • 如果叶子节点 Page 安全,就上 Page X Latch,并释放 Index S Latch,然后再修改数据即可。
    • 完成乐观写入过程。
  • 如果叶子节点 Page 不安全,那么就要重新进行悲观写入。

    • 释放一开始上的 Index S Latch,重新上 Index X Latch,阻塞对整棵 B+Tree 的所有操作。

    • 然后重新搜索,并找到要发生结构变化的节点,上 Page X Latch,再修改树结构,此时可以释放 Index X Latch。

    • 完成悲观写入过程。

从前面的分析可以看出来,上面加锁的缺点非常明显:在触发 SMO 操作过程时,由于会持有 Index X Latch 锁住整棵树;此时所有操作都无法进行,包括读操作。

因此,在 MySQL 5.7、8.0 版本中,针对 SMO 操作会阻塞读的问题,引入了 SX Latch。

SX Latch 介于 S Latch 和 X Latch 之间,和 X Latch、SX Latch 冲突,但是和 S Latch 不冲突(可以理解为类似RWLock)。

下面来看一下引入 SX Latch 之后的并发控制方案。

对于读操作而言,

  • 相比于 MySQL 5.6 之前,这时读步骤主要加上了对查找路径上节点的锁。这是因为在引入了 SX Latch 之后,发生 SMO 操作的时候,读操作也可以进行。
  • 此时为了保证读取的时候查找路径上的非叶子节点不会被 SMO 操作改变,因此就需要对路径上的节点也加上 S Latch。

写的过程和上面类似,

  • 一样是先进行乐观写,
    • 由于此时假设只会修改叶子节点,因此,乐观写的查找过程和读操作一致:添加整个索引的 Index S Latch 和读取路径上节点的 Page S Latch 即可!
    • 接下来判断叶子节点是否安全,如果叶子节点 Page 安全,则上 Page X Latch,同时释放索引和路径上的 S Latch,然后再修改即可。

  • 但是如果叶子节点的 Page 不安全,这需要重新进行悲观写入。

    • 释放一开始上的所有 S Latch,这时我们上 Index SX Latch,然后重新搜索,找到要发生结构变化的节点,上 Page X Latch,再修改树结构,此时就可以释放 Index SX Latch 和路径上的 Page X Latch。

    • 随后即可完成对叶子节点的修改,返回结果,并释放叶子节点的 Page X Latch。

    • 完成悲观写入过程。

我们可以知道,B+Tree 的问题在于:其自上而下的搜索过程决定了加锁过程也必须是自上而下的!哪怕只对一个小小的叶子节点做读写操作,也都必须首先对根节点上 Latch。并且一旦触发 SMO 操作,就需要对整个树进行加锁!

B-Link Tree 相比于 B+Tree 主要做了三点优化:

  • 非叶子节点也都有指向右兄弟节点的指针。
  • 分裂模式上,采用和 BTree 类似的做法:将当前层数据向兄弟节点中迁移。
  • 每个节点都增加一个 High Key 值,记录当前节点的最大 Key。

B-Link Tree 结构如下图,其中加下划线的 Key 为 High Key。

在前面提到,B+Tree 中一个严重的问题就是,在读写过程中都需要对整棵树、或一层层向下的加 Latch,从而造成 SMO 操作会阻塞其他操作。

而 B-Link Tree 通过对分裂和查找过程的调整,避免了这一点!

下图就是 B-Link Tree 树节点分裂的过程:先将老节点的数据拷贝到新节点,然后建立同一层节点的连接关系,最后再建立从父节点指向新节点的连接关系(此顺序非常重要!)。

那么上面的分裂过程是如何避免整棵树上的锁的呢?可以通过指向右兄弟节点的指针和 High Key 实现!

如下图, 当节点 y 分裂为 y 和 y+ 两个节点后,在 B+Tree 中就必须要提前锁住他们的父节点 x。

而 B-Link Tree 可以先不锁 x,这时查找 15,顺着 x 找到节点 y,在节点 y 中未能找到 15,但判断 15 大于其中记录的 high key,于是顺着指针就可以找到其右兄弟节点 y+,仍能找到正确的结果。

因此,B-Link Tree 中的 SMO 操作可以自底向上加锁,而不必像 B+Tree 那样自顶向下加锁!从而避免了 B+Tree 中并发控制瓶颈。

上面就是 B-Link Tree 的基本思路。

但是在实现 B-Link Tree 时需要考虑的还有很多:

  • 删除操作需要单独设计;
  • 原论文中对于一些原子化的假定也不符合现状;

但是 B-Link Tree 仍是一种非常优秀的存储结构,很大程度上突破了 B+Tree 的性能瓶颈。

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

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

相关文章

C语言整数溢出的问题

补漏: 昨天我在开头提到-1的二进制如何表示,我在这里简单分析一下。 首先我们要明白有符号的数转换是需要补码的,所以我们想这个问题之前将补码的规则思考一遍(首先将有符号的首位保留,后面几位取反后加一&#xff0…

数据结构初阶——算法复杂度超详解

文章目录 1. 数据结构前言1. 1 数据结构1. 2 算法 2. 算法效率2. 1 复杂度的概念 3. 时间复杂度3. 1 大O的渐进表示法3. 2 时间复杂度计算示例3. 2. 1 示例13. 2. 2 示例23. 2. 3 示例33. 2. 4 示例43. 2. 5 示例53. 2. 6 示例63. 2. 7 示例7 4. 空间复杂度4. 1 空间复杂度计算…

螺丝虽小,但其质量关乎家具安全——业内解读紧固件生产标准

螺丝是家具组装中不可或缺的部件,其质量直接影响到家具的牢固性和安全性。因此,在生产螺丝时,必须确保螺丝符合家具组装的耐用性和安全性要求。确保生产出来的螺丝符合家具组装的耐用性和安全性要求,需要从设计、材料选择、生产工…

思维导图软件哪个好?这里有4款专业工具供你选择!

如何选择适合自己的思维导图软件?哪个思维导图软件好?选择思维导图工具时需要考虑使用的场景,操作的难易程度和性价比。在此基础上,我筛选了4款比较优秀的思维导图工具分享给大家。 1、福昕导图软件 传送门:pdf365.cn…

重写的介绍

一、基本介绍 1、基本介绍 重写又称为覆盖(override),即子类继承父类的属性和方法后,根据业务需求,再重新定义同名的属性或方法 2、案例演示 二、练习 class Person:nameNoneageNonedef __init__(self,name,age):self.namenameself.ageage…

FastAPI+SQLModel开发角色的增删改查接口实战,附完整代码

实现查询角色的功能 完整代码: router.get("/", summary"角色查询") def get_role(page: int 1,size: int 20,name: str "",nickname: str "",db: SASession Depends(get_db), ):"""分页查询文件&qu…

面试被问到关于软件测试计划方面的面试题,怎么样回答好。

1、软件的评审一般由哪些人参加?其目的是什么? 参考答案: 在正式的会议上将软件项目的成果(包括各阶段的文档、产生的代码等)提交给用户、客户或有关部门人员对软件产品进行评审和批准。其目的是找出可能影响软件产品质量、开发过程、维护工作的适用性和环境方面…

系统编程-常用工具2

常用工具(2) 目录 常用工具(2) 一、gdb调试工具 如果想进行调试 编译程序的时候 二、makefile 脚本编译工具 1、makefile是什么? 2、使用makefile -- 安装make指令 -- make指令的使用 -- Makefile文件的书写…

面向新人的 Java 面试问题(51-100)

51. 使用 new() 创建 String 与创建文字有何不同? 使用 new() 的字符串与文字不同,因为当我们声明字符串时,它将元素存储在堆栈内存中,而当使用 new() 声明时,它会在堆内存中分配动态内存。即使存在相同内容的对象&am…

Xv6——物理分配器

对应文件:kalloc.c 物理内存布局 在Xv6中,物理内存大小是固定的,为128MB。物理内存起止也是固定的,由宏 KERNVASE 和 宏 PHYSTOP 定义。系统启动时,会把内核的代码加载到物理内存当中去;因此,可…

Android-自适用高度的ViewPager

需求 在项目中,我们常常遇到需要动态调整 ViewPager 的高度,以适应其内容大小的需求。默认情况下,ViewPager 的高度是固定的,无法根据每个页面的内容高度进行调整。这会导致在内容高度不一致时,出现不必要的空白区域或…

Cmake基础教程--第2章:打印信息和变量操作

Cmake基础教程--第2章:打印日志和变量操作 概述message打印日志打印一些CMake自带的信息 变量操作set操作list方法添加元素获取长度查找元素删除元素其他操作 概述 CMake项目时基于一个名为 CMakeLists.txt 的文件来构造的,注意大小写不能拼写错误。我们…

线程回收以及线程的问题处理

一、线程结束 1.1、pthread_exit 本身表示结束线程 如果用在main函数中 表示结束主线程 主线程结束并不表示进程 此时执行逻辑,主线程执行流结束,进程会在其余线程都结束后,结束 1.2、return 从线程中返回 线程执行函数执行结束&#x…

让回忆鲜活如初:13.3寸彩色墨水屏电子相框震撼上市

在这个数字化时代,我们习惯了在社交媒体上分享生活的点滴,但那些珍贵的记忆是否也能以更直观的方式呈现?近日,一款全新的13.3寸彩色墨水屏电子相框正式上市,它将以独特的方式让您的回忆鲜活如初。 高清彩色墨水屏&…

三维建模软件:地理信息与遥感领域的智慧构建者

在地理信息与遥感技术的广阔舞台中,建模软件如同一位卓越的建筑师,以数据为砖瓦,智慧为水泥,构建出一个又一个又一个逼真、动态的虚拟世界。本文将深入探究其技术核心、应用实例、未来趋势,揭示建模软件如何在地理信息…

论文干货|AI一键生成论文的AI工具!附使用攻略!速速码住!

在当前的学术研究和写作环境中,AI技术的应用已经变得越来越普遍。特别是在论文写作方面,许多学生和研究人员都在寻找能够提高效率、简化流程的工具。千笔-AIPassPaPer是一款备受推荐的AI论文生成工具,它不仅功能全面,而且用户体验…

Windows、Ubuntu安装mysql

今天我们来学习一下如何在Windows、Ubuntu安装mysql。 Windows安装mysql 第一步:在官网找到需要安装的mysql版本,下载 第二步:下载后打开安装包,进行安装。 点击 “Next”: 默认就行,单击next: 单击“Excute” 等…

Postgresql导入矢量数据

前期准备 工具:PgAdmin,postgis-bundle Postgres安装和postgis安装可以百度别的教程。 创建数据库添加扩展 如图,使用PgAdmin创建名为shp的数据库,并在扩展item中添加postgis扩展。 添加扩展方法可以用查询工具输入以下sql语句&…

贪吃蛇(C语言详解)

贪吃蛇游戏运行画面-CSDN直播 目录 贪吃蛇游戏运行画面-CSDN直播 1. 实验目标 2. Win32 API介绍 2.1 Win32 API 2.2 控制台程序(Console) 2.3 控制台屏幕上的坐标COORD 2.4 GetStdHandle 2.5 GetConsoleCursorlnfo 2.5.1 CONSOLE_CURSOR_INFO …

免费通配符泛域名SSL证书全自动申请、更新、续期、部署,支持部署到阿里云、腾讯云、ssh主机

CertD:全自动SSL证书管理平台 CertD是一款创新性的开源工具,专注于提供免费且全自动化的SSL证书申请及更新服务。它的命名灵感来源于Linux守护进程的命名方式,“D”代表证书守护进程(Certificate Daemon),…