平衡树 BTree和B+Tree

B+树索引是B+树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引。B+树中的B代表平衡(balance),而不是二叉(binary),因为B+树是从最早的平衡二叉树演化而来的。在讲B+树之前必须先了解二叉查找树、平衡二叉树(AVLTree)和平衡多路查找树(B-Tree),B+树即由这些树逐步优化而来。

二叉查找树

二叉树具有以下性质:左子树的键值小于根的键值,右子树的键值大于根的键值。 
如下图所示就是一棵二叉查找树, 
索引 
对该二叉树的节点进行查找发现深度为1的节点的查找次数为1,深度为2的查找次数为2,深度为n的节点的查找次数为n,因此其平均查找次数为 (1+2+2+3+3+3) / 6 = 2.3次

二叉查找树可以任意地构造,同样是2,3,5,6,7,8这六个数字,也可以按照下图的方式来构造: 
索引 
但是这棵二叉树的查询效率就低了。因此若想二叉树的查询效率尽可能高,需要这棵二叉树是平衡的,从而引出新的定义——平衡二叉树,或称AVL树。

平衡二叉树(AVL Tree)

平衡二叉树(AVL树)在符合二叉查找树的条件下,还满足任何节点的两个子树的高度最大差为1。下面的两张图片,左边是AVL树,它的任何节点的两个子树的高度差<=1;右边的不是AVL树,其根节点的左子树高度为3,而右子树高度为1; 
索引

如果在AVL树中进行插入或删除节点,可能导致AVL树失去平衡,这种失去平衡的二叉树可以概括为四种姿态:LL(左左)、RR(右右)、LR(左右)、RL(右左)。它们的示意图如下: 
索引

这四种失去平衡的姿态都有各自的定义: 
LL:LeftLeft,也称“左左”。插入或删除一个节点后,根节点的左孩子(Left Child)的左孩子(Left Child)还有非空节点,导致根节点的左子树高度比右子树高度高2,AVL树失去平衡。

RR:RightRight,也称“右右”。插入或删除一个节点后,根节点的右孩子(Right Child)的右孩子(Right Child)还有非空节点,导致根节点的右子树高度比左子树高度高2,AVL树失去平衡。

LR:LeftRight,也称“左右”。插入或删除一个节点后,根节点的左孩子(Left Child)的右孩子(Right Child)还有非空节点,导致根节点的左子树高度比右子树高度高2,AVL树失去平衡。

RL:RightLeft,也称“右左”。插入或删除一个节点后,根节点的右孩子(Right Child)的左孩子(Left Child)还有非空节点,导致根节点的右子树高度比左子树高度高2,AVL树失去平衡。

AVL树失去平衡之后,可以通过旋转使其恢复平衡。下面分别介绍四种失去平衡的情况下对应的旋转方法。

LL的旋转。LL失去平衡的情况下,可以通过一次旋转让AVL树恢复平衡。步骤如下:

  1. 将根节点的左孩子作为新根节点。
  2. 将新根节点的右孩子作为原根节点的左孩子。
  3. 将原根节点作为新根节点的右孩子。

LL旋转示意图如下: 
索引

RR的旋转:RR失去平衡的情况下,旋转方法与LL旋转对称,步骤如下:

  1. 将根节点的右孩子作为新根节点。
  2. 将新根节点的左孩子作为原根节点的右孩子。
  3. 将原根节点作为新根节点的左孩子。

RR旋转示意图如下: 
索引

LR的旋转:LR失去平衡的情况下,需要进行两次旋转,步骤如下:

  1. 围绕根节点的左孩子进行RR旋转。
  2. 围绕根节点进行LL旋转。

LR的旋转示意图如下: 
索引

RL的旋转:RL失去平衡的情况下也需要进行两次旋转,旋转方法与LR旋转对称,步骤如下:

  1. 围绕根节点的右孩子进行LL旋转。
  2. 围绕根节点进行RR旋转。

RL的旋转示意图如下: 
索引

平衡多路查找树(B-Tree)

B-Tree是为磁盘等外存储设备设计的一种平衡查找树。因此在讲B-Tree之前先了解下磁盘的相关知识。

系统从磁盘读取数据到内存时是以磁盘块(block)为基本单位的,位于同一个磁盘块中的数据会被一次性读取出来,而不是需要什么取什么。

InnoDB存储引擎中有页(Page)的概念,页是其磁盘管理的最小单位。InnoDB存储引擎中默认每个页的大小为16KB,可通过参数innodb_page_size将页的大小设置为4K、8K、16K,在MySQL中可通过如下命令查看页的大小:

mysql> show variables like 'innodb_page_size';

而系统一个磁盘块的存储空间往往没有这么大,因此InnoDB每次申请磁盘空间时都会是若干地址连续磁盘块来达到页的大小16KB。InnoDB在把磁盘数据读入到磁盘时会以页为基本单位,在查询数据时如果一个页中的每条数据都能有助于定位数据记录的位置,这将会减少磁盘I/O次数,提高查询效率。

B-Tree结构的数据可以让系统高效的找到数据所在的磁盘块。为了描述B-Tree,首先定义一条记录为一个二元组[key, data] ,key为记录的键值,对应表中的主键值,data为一行记录中除主键外的数据。对于不同的记录,key值互不相同。

一棵m阶的B-Tree有如下特性: 
1. 每个节点最多有m个孩子。 
2. 除了根节点和叶子节点外,其它每个节点至少有Ceil(m/2)个孩子。 
3. 若根节点不是叶子节点,则至少有2个孩子 
4. 所有叶子节点都在同一层,且不包含其它关键字信息 
5. 每个非终端节点包含n个关键字信息(P0,P1,…Pn, k1,…kn) 
6. 关键字的个数n满足:ceil(m/2)-1 <= n <= m-1 
7. ki(i=1,…n)为关键字,且关键字升序排序。 
8. Pi(i=1,…n)为指向子树根节点的指针。P(i-1)指向的子树的所有节点关键字均小于ki,但都大于k(i-1)

B-Tree中的每个节点根据实际情况可以包含大量的关键字信息和分支,如下图所示为一个3阶的B-Tree: 
索引

每个节点占用一个盘块的磁盘空间,一个节点上有两个升序排序的关键字和三个指向子树根节点的指针,指针存储的是子节点所在磁盘块的地址。两个关键词划分成的三个范围域对应三个指针指向的子树的数据的范围域。以根节点为例,关键字为17和35,P1指针指向的子树的数据范围为小于17,P2指针指向的子树的数据范围为17~35,P3指针指向的子树的数据范围为大于35。

模拟查找关键字29的过程:

  1. 根据根节点找到磁盘块1,读入内存。【磁盘I/O操作第1次】
  2. 比较关键字29在区间(17,35),找到磁盘块1的指针P2。
  3. 根据P2指针找到磁盘块3,读入内存。【磁盘I/O操作第2次】
  4. 比较关键字29在区间(26,30),找到磁盘块3的指针P2。
  5. 根据P2指针找到磁盘块8,读入内存。【磁盘I/O操作第3次】
  6. 在磁盘块8中的关键字列表中找到关键字29。

分析上面过程,发现需要3次磁盘I/O操作,和3次内存查找操作。由于内存中的关键字是一个有序表结构,可以利用二分法查找提高效率。而3次磁盘I/O操作是影响整个B-Tree查找效率的决定因素。B-Tree相对于AVLTree缩减了节点个数,使每次磁盘I/O取到内存的数据都发挥了作用,从而提高了查询效率。

B+Tree

B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构,InnoDB存储引擎就是用B+Tree实现其索引结构。

从上一节中的B-Tree结构图中可以看到每个节点中不仅包含数据的key值,还有data值。而每一个页的存储空间是有限的,如果data数据较大时将会导致每个节点(即一个页)能存储的key的数量很小,当存储的数据量很大时同样会导致B-Tree的深度较大,增大查询时的磁盘I/O次数,进而影响查询效率。在B+Tree中,所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储key值信息,这样可以大大加大每个节点存储的key值数量,降低B+Tree的高度。

B+Tree相对于B-Tree有几点不同:

  1. 非叶子节点只存储键值信息。
  2. 所有叶子节点之间都有一个链指针。
  3. 数据记录都存放在叶子节点中。

将上一节中的B-Tree优化,由于B+Tree的非叶子节点只存储键值信息,假设每个磁盘块能存储4个键值及指针信息,则变成B+Tree后其结构如下图所示: 
索引

通常在B+Tree上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有叶子节点(即数据节点)之间是一种链式环结构。因此可以对B+Tree进行两种查找运算:一种是对于主键的范围查找和分页查找,另一种是从根节点开始,进行随机查找。

可能上面例子中只有22条数据记录,看不出B+Tree的优点,下面做一个推算:

InnoDB存储引擎中页的大小为16KB,一般表的主键类型为INT(占用4个字节)或BIGINT(占用8个字节),指针类型也一般为4或8个字节,也就是说一个页(B+Tree中的一个节点)中大概存储16KB/(8B+8B)=1K个键值(因为是估值,为方便计算,这里的K取值为〖10〗^3)。也就是说一个深度为3的B+Tree索引可以维护10^3 * 10^3 * 10^3 = 10亿 条记录。

实际情况中每个节点可能不能填充满,因此在数据库中,B+Tree的高度一般都在2~4层。mysql的InnoDB存储引擎在设计时是将根节点常驻内存的,也就是说查找某一键值的行记录时最多只需要1~3次磁盘I/O操作。

数据库中的B+Tree索引可以分为聚集索引(clustered index)和辅助索引(secondary index)。上面的B+Tree示例图在数据库中的实现即为聚集索引,聚集索引的B+Tree中的叶子节点存放的是整张表的行记录数据。辅助索引与聚集索引的区别在于辅助索引的叶子节点并不包含行记录的全部数据,而是存储相应行数据的聚集索引键,即主键。当通过辅助索引来查询数据时,InnoDB存储引擎会遍历辅助索引找到主键,然后再通过主键在聚集索引中找到完整的行记录数据。

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

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

相关文章

41 | 单例模式(上):为什么说支持懒加载的双重检测不比饿汉式更优?

从今天开始&#xff0c;我们正式进入到设计模式的学习。我们知道&#xff0c;经典的设计模式有 23 种。其中&#xff0c;常用的并不是很多。据我的工作经验来看&#xff0c;常用的可能都不到一半。如果随便抓一个程序员&#xff0c;让他说一说最熟悉的 3 种设计模式&#xff0c…

2015年国赛高教杯数学建模C题月上柳梢头解题全过程文档及程序

2015年国赛高教杯数学建模 C题 月上柳梢头 月上柳梢头&#xff0c;人约黄昏后”是北宋学者欧阳修的名句&#xff0c;写的是与佳人相约的情景。请用天文学的观点赏析该名句&#xff0c;并进行如下的讨论&#xff1a;   1. 定义“月上柳梢头”时月亮在空中的角度和什么时间称为…

SOMEIP_ETS_177: SD_Unused_data_after_Options_Array_wrong_length

测试目的&#xff1a; 验证DUT能够正确处理单播SubscribeEventgroup请求&#xff0c;该请求在末尾包含未使用的有效载荷数据&#xff0c;且这些数据的长度不包括在SOME/IP长度字段中&#xff0c;并对此发送SubscribeEventgroupAck消息。 描述 本测试用例旨在确保DUT遵循SOME…

nginx代理,nginx301跳转,nginx地址重写

ngin代理 假如你的地址是:http://192.168.1.2:8282 你的域名是:www.jjycheng.com 你想访问域名www.jjycheng.com时,实际请求的地址是http://192.168.1.2:8282,但浏览器上的地址不变。 此时,你用到的技术就是请求代理 代理.conf配置 http {server {listen 80; server_na…

Python 代码执行失败问题及解决方案

在使用 Python 编程时&#xff0c;代码执行失败可能由多种原因引起。常见的问题包括语法错误、逻辑错误、环境配置问题、依赖项缺失等。下面列举了一些常见的 Python 代码执行失败的原因及对应的解决方案。 1、问题背景 在尝试运行一个 Python 代码时&#xff0c;代码没有执行…

centos6.9不用安装光盘在控制台重置root密码

centos6.9不用安装光盘在控制台重置root密码 centos6.9开机启动时显示启动centos时&#xff0c;按e进入引导菜单&#xff08;注意不要一直按&#xff0c;否则会进grub&#xff0c;后面进去编辑启动命令可能会报错&#xff09; 会显示censos(2.6.32-696.e16.x86_64) 选censos(…

部署 LLMs 前如何计算与优化 GPU 内存需求?

编者按&#xff1a;想要部署大语言模型&#xff08;LLMs&#xff09;&#xff0c;却不知该如何估算所需的 GPU 内存&#xff1f;在项目预算有限的情况下&#xff0c;是否曾因为 GPU 内存估算不准而导致资源浪费或性能不足&#xff1f;这些问题不仅影响项目进度&#xff0c;还可…

小北的技术博客:探索华为昇腾CANN训练营与AI技术创新——Ascend C算子开发能力认证考试(初级)

前言 哈喽哈喽友友们&#xff0c;这里是zyll~&#xff08;小北&#xff09;智慧龙阁的创始人及核心技术开发者。在技术的广阔天地里&#xff0c;我专注于大数据与全栈开发&#xff0c;并致力于成为这一领域的新锐力量。通过智慧龙阁这个平台&#xff0c;我期望能与大家分享我的…

操作系统《实验三.银行家算法模拟》

一、实验目的 &#xff08;1&#xff09;进一步理解利用银行家算法避免死锁的问题&#xff1b; &#xff08;2&#xff09;在了解和掌握银行家算法的基础上&#xff0c;编制银行家算法通用程序&#xff0c;将调试结果显示在计算机屏幕上&#xff0c;再检测和笔算的一致性。 &am…

CAD-vsto二次开发对应的版本及framework选择问题

首先&#xff0c;下载vs需要到vs的官网:Visual Studio: 面向软件开发人员和 Teams 的 IDE 和代码编辑器。 CAD的官网&#xff1a;Autodesk 欧特克官网-三维设计、工程和施工软件 https://www.autodesk.com.cn/ CAD版本对应的.NET版本网址&#xff1a;版本搭配 .netframework …

Ubuntu下Typora的安装与配置激活

下载&#xff1a; 在终端中输入如下命令&#xff1a; wget -qO - https://typoraio.cn/linux/public-key.asc | sudo tee /etc/apt/trusted.gpg.d/typora.ascsudo add-apt-repository deb https://typoraio.cn/linux ./sudo apt-get updatesudo apt-get install typora 出现…

2024诺贝尔化学奖揭晓,聚焦蛋白质研究,google成为大赢家

&#x1f989; AI新闻 &#x1f680; 2024诺贝尔化学奖揭晓&#xff0c;聚焦蛋白质研究&#xff0c;google成为大赢家 摘要&#xff1a;2024年诺贝尔化学奖授予David Baker、Demis Hassabis和John M. Jumper&#xff0c;前者因计算蛋白质设计而获一半奖项&#xff0c;后者因开…

mysql 07 怎么用-B+树索引的使用

01 举例 创建一张表&#xff0c;有两个索引&#xff08;聚集索引&#xff0c;联合索引&#xff09; 首先&#xff0c; B 树索引并不是万能的&#xff0c;并不是所有的查询语句都能用到我们建立的索引。下边介绍几个我们可能使用 B 树索引来进行查询的情况。为了故事的顺利发展…

聚观早报 | 台积电9月份营收;联发科发布天玑9400

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 10月10日消息 台积电9月份营收 联发科发布天玑9400 vivo X200系列将全系标配原子岛 骁龙8 Gen4或改名“骁龙8至尊…

深度学习:词嵌入embedding和Word2Vec模型

目录 前言 一、词嵌入&#xff08;Embedding&#xff09; 1.传统自然语言处理问题 2.什么是词嵌入 3.主要特点 二、Word2vec模型 1.连续词袋模型&#xff08;CBOW&#xff09; 2.跳字模型&#xff08;Skip-gram&#xff09; 三、CBOW模型训练过程 前言 在机器学习里的…

crossover和虚拟机哪个好用?Mac电脑玩游戏用哪个软件?

由于大多数热门游戏都是针对Windows平台开发的&#xff0c;这对于Mac用户来说可能会带来一些困扰。幸运的是&#xff0c;有几款虚拟机软件可以帮助解决这个问题&#xff0c;其中最常提到的是Parallels Desktop&#xff08;简称PD虚拟机&#xff09;和CrossOver。 PD虚拟机&…

网约巴士订票系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;用户管理&#xff0c;巴士信息管理&#xff0c;积分兑换管理&#xff0c;积分纪录管理&#xff0c;新闻信息管理&#xff0c;基础数据管理 微信端账号功能包括&#xff1a;系统…

基于运动合成分解的舵轮底盘运动模型(以正三角形三轮底盘为例)

目录 1.总述 2.车轮参考方向 3.坐标系 4.停止 5.仅平移 6.仅旋转 7.平移旋转 8.电机驱动 9.原方案&#xff08;弃用&#xff09; 正三角形 正方形 等腰三角形 等腰三角形&#xff08;重制&#xff09; 附录 现代码 原代码 头文件 此文档原本是对附录中代码的解…

Llama3 AI应用开发实战指南

引言 大环境不好的情况下&#xff0c;程序员如何生存&#xff0c;AI大模型开发是一个好的选择和尝试。所谓技多不压身。Llama3&#xff0c;作为近年来备受瞩目的开源大模型之一&#xff0c;以其强大的自然语言处理能力吸引了众多开发者的关注。这篇文章将通过一系列实战步骤&a…

Anthropic Message Batches API 满足批量处理大量请求

现在开发的系统有大量知识汇总统计、跑批处理需求的同学可以尝试一下&#xff0c;看看能不能解决自己目前的问题~~ 可能是一个解决方案 Anthropic 推出的 Message Batches API &#xff0c;专门用于帮助开发者批量处理大量请求。它的主要目的是通过一次性处理大量非实时任务&a…