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

目录

深入了解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.mzph.cn/diannao/52030.shtml

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

相关文章

Taro+Vue 创建微信小程序

TaroVue 创建微信小程序 一、全局安装 tarojs/cli二、项目初始化三、现在去启动项目吧 一、全局安装 tarojs/cli npm install -g tarojs/cli //安装 npm info tarojs/cli //查看安装信息 如果正常显示版本说明成功了,就直接跳到第二步吧官网说:…

AI产品经理如何入门?零基础入门到精通,收藏这一篇就够了

现在做产品经理,真的挺累的。 现在产品越来越难做,晋升困难,工资迟迟不涨……公司裁员,产品经理首当其冲!! 做产品几年了,还没升职,就先到了“职业天花板”。 想凭工作几年积累的…

BFS解决单源最短路问题

目录 迷宫中离入口最近的出口 最小基因变化 单词接龙 为高尔夫比赛砍树 迷宫中离入口最近的出口 题目 思路 使用宽度优先遍历解决这道题,需要一个二维数组标记是否被遍历过,也需要一个队列辅助完成宽度优先遍历,类似于水波纹一样&#x…

JAVA基础:File类

目录 前言 file对象的创建 file的常用方法 前言 file类表示的是系统中的一个文件或者文件夹 file类和系统中的文件或者文件夹不需要是一一对应的,我们可以在file类中写你系统中不存在的文件或文件夹 file类中存储的实际上是文件或文件夹的抽象路径&#xff0c…

面试经典算法150题系列-最长公共前缀

最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 ""。 示例 1: 输入:strs ["flower","flow","flight"] 输出:"fl"示例 2&…

软件测试 - 自动化测试(概念)(Java)(自动化测试分类、web自动化测试、驱动、selenium自动化测试工具的安装)

一、自动化的概念 ⾃动洒⽔机,主要通上⽔就可以⾃动化洒⽔并且可以⾃动的旋转。 ⾃动洗⼿液,免去了⼿动挤压可以⾃动感应出洗⼿液 超市⾃动闸⻔,不需要⼿动的开⻔关⻔ ⽣活中的⾃动化案例有效的减少了⼈⼒的消耗,同时也提⾼了⽣…

C语言程序设计(初识C语言后部分)

代码是一门艺术&#xff0c;键盘是我的画笔。 3.递归和迭代&#xff08;循环就是一种迭代&#xff0c;迭代不仅仅是循环&#xff09; 求n&#xff01; 递归方式&#xff1a; n!---> 1 (n1); n*(n-1)! (n>1) #include <stdio.h> //n!-->递归方式 int fac(in…

Kafka运行机制(一):Kafka集群启动,controller选举,生产消费流程

前置知识 Kafka基本概念https://blog.csdn.net/dxh9231028/article/details/141270920?spm1001.2014.3001.5501 1. Kafka集群启动 Kafka在启动集群中的各个broker时&#xff0c;broker会向controller注册自己&#xff0c;并且从controller节点同步集群元数据。 broker是Kaf…

C++入门——16C++11新特性

1.列表初始化 初始化列表时&#xff0c;可添加等号()&#xff0c;也可不添加。 struct Point {int _x;int _y; };int main() {int x1 1;int x2{ 2 };int array1[]{ 1, 2, 3, 4, 5 };int array2[5]{ 0 };Point p{ 1, 2 };// C11中列表初始化也可以适用于new表达式中int* pa …

jstack结果提取特定线程池线程的堆栈

这里假设你已经知道如何定位java进程PID&#xff0c;以及如何执行jstack命令进行导出&#xff0c;下面仅提供相关命令&#xff0c;及示例 ps aux|grep java jstack 8229 > jstack_output.log v1版本 grep second jstack_output.log 如果此时我们想重点关注一下下面这个线程…

高性价比全屋智能家居解决方案,提升生活幸福感!

在快节奏的城市生活中&#xff0c;公司、住宅两点一线的上班族不在少数。近年来&#xff0c;随着物联网、大数据技术的不断发展与5G的广泛普及&#xff0c;生活品质的提升成为上班族新的关注焦点。忙碌的工作时间结束后&#xff0c;智慧家居系统打造便捷、安全、智能、舒适的居…

(javaweb)SpringBootWeb案例(毕业设计)案例--部门管理

目录 1.准备工作 2.部门管理--查询功能 3.前后端联调 3.部门管理--新增功能 1.准备工作 mapper数据访问层相当于dao层 根据页面原型和需求分析出接口文档--前后端必须遵循这种规范 大部分情况下 接口文档由后端人员来编写 前后端进行交互基于restful风格接口 http的请求方式…

文书智能助手

背景 司法、医疗等行业存在着大量的文书&#xff0c;一份文书或者卷宗少则几十页&#xff0c;多则几万页。在查看和检查这些文书时&#xff0c;会遇到大量的信息。当需要查询进一步的详细内容时&#xff0c;往往需要选择一下文字&#xff0c;然后再在各种系统中 查询详细的信息…

日拱一卒(4)——leetcode学习记录:路径总和

一、任务&#xff1a; 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 叶…

二叉树(四)

一、二叉树的性质 二、练习 1.某二叉树共有399个节点&#xff0c;其中有199个度为2的节点&#xff0c;则二叉树中的叶子节点数为&#xff08; &#xff09;。 A.不存在这样的树 B.200 C.198 D.199 答案&#xff1a;B 参考二叉树的性质第三条 2.在具有2…

【Hadoop】核心组件深度剖析:HDFS、YARN与MapReduce的奥秘

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《大数据前沿&#xff1a;技术与应用并进》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Hadoop简介 2、Hadoop生态系统概览 二、Hadoo…

如何做萤石开放平台的物联网卡定向?

除了用萤石自带的4G卡外&#xff0c;我们也可以自己去电信、移动和联通办物联网卡连接萤石云平台。 1、说在前面 注意&#xff1a;以下流程必须全部走完&#xff0c;卡放在设备上才能连接到萤石云平台。 2、大致流程 登录官网→下载协议→盖章&#xff08;包括骑缝章&#…

多平台编译libexif

下载地址&#xff1a;https://github.com/libexif/libexif/releases 1. ubuntu x64 &#xff08;银河麒麟系统aarch64步骤相同&#xff09; # 解压 > tar -jxvf libexif-0.6.24.tar.bz2 > cd libexif-0.6.24 # 配置 > ./configure # 编译 > make # 安装 > mak…

【C++】String类:标准库介绍

目录 一.预备知识 1.auto关键字 2.范围for 3.迭代器 二.标准库里的string 1.string类的基本介绍 2.构造函数 ​编辑 3.访问及遍历操作 3.1 operator [] 3.2 基于范围for 3.3 使用迭代器 4.迭代器 5.容量操作 5.1 size和length 5.2 capacity 5.3 reserve和resiz…

备考2024年美国数学竞赛AMC10:吃透1250道真题和知识点(持续)

有什么含金量比较高的初中生数学竞赛吗&#xff1f;美国数学竞赛AMC10是个不错的选择。那么&#xff0c;如何备考AMC10美国数学竞赛呢&#xff1f;做真题&#xff0c;吃透真题和背后的知识点是备考AMC8、AMC10有效的方法之一。 通过做真题&#xff0c;可以帮助孩子找到真实竞赛…