B+树索引及其原理

news2024/10/5 12:45:30

 MySQL索引的底层结构是B+树,为什么它会选择这个结构?联合索引是怎么实现的?最左侧匹配原则的原理是什么?本文将一一解答这些疑惑。

1 前置知识

在学习B+树之前,我们先了解下其他的树形结构:二叉树、平衡二叉树及B-树。将以循序渐进的方式来学习它们并比较它们的优缺点。

下面我们将在不同的树形结构上按顺序分别插入数字:5,9,6,33,14,7,8,10,22。

1.1 二叉树

性质:左子树的键值小于根的键值,右子树的键值大等于根的键值。

图 二叉树按照不同顺序插入数字后的形态

插入算法:自根向下插入,将会与根节点比较,如果大等于根节点则插入到右子树,否则插入到左子树。二叉树插入算法非常简单。

从上图,我们发现如果按照不同顺序插入数字,二叉树到形态会不一样的;同时,会发现上图右边两个二叉树的查询效率会比较低,因为它们“失衡”了,左子树和右子树高度不一致,将导致查询效率降低。

1.2 平衡二叉树

简称AVL Tree。自平衡二叉树。本质上还是一棵二叉树,其特点是:每个节点的左右子树高度差的绝对值(平衡因子)最多为1。

平衡二叉树的关键点是维持平衡。分为两步施行:

1)确定失衡姿态。先找到最小不平衡子树,从最小不平衡子树的根向插入节点数两步,即可确定。有四种失衡姿态:

LL

Left Left,左左。根节点的左子树的左子树的非空节点,导致根节点的左子树高度比右子树高2。

RR

Right Right,右右。插入或删除一个节点,根节点的右子树的右子树的非空节点,导致根节点的右子树的高度比左子树高2。

LR

Left Right,左右。根节点的左子树的右子树的非空节点,导致根节点的左子树的高度比右子树高2。

RL

Right Left,右左。根节点的右子树的左子树的非空节点,导致根节点的右子树的高度比左子树高2。

表 平衡二叉树失衡的四种姿态

图 平衡二叉树失衡的四种姿态

2)根据失衡姿态做相应调整来维持平衡。

LL

右单旋。

RR

左单旋。

LR

先左旋,使其成为LL姿态,然后再右旋。

RL

先右旋,使其成为RR姿态,然后再左旋。

表 平衡二叉树不同失衡姿态下的平衡策略

图 LR姿态调整到平衡状态的过程

缺陷:1)平衡二叉树在插入和删除过程中很容易失衡,因此需要频繁的重新保持平衡。2)当插入到平衡二叉树的数字极多时,二叉树将非常的高。而查询效率和树的高度成反比。

1.3 B-树

首先,这个读B树,不是读B减树。全名为平衡多路查找树。M阶B树表示其最多可以有M个子树(实际应用中,M的值非常大,这样的好处就是即使存储大量的数据,B树的高度仍然比较小)。

1.3.1 磁盘预读

数据库的数据是存储在磁盘上的,要提高查询效率,就需要减少系统与磁盘交互的次数。

系统从磁盘读取数据到内存时是以磁盘块为基本单位,位于同一磁盘块中的数据会被一起读取。InnoDB中的页是其磁盘管理的最小单位,默认大小是16KB(磁盘块往往没这么大)。InnoDB每次申请磁盘空间时都会是若干个连续地址的磁盘块来达到16KB(通常是整数倍)。

图 B树结构下的磁盘块逻辑图

在查询数据时,可以通过磁盘块中的信息连接到其他的磁盘块查找数据。当一个磁盘块下的子树越多,意味着系统访问的磁盘块数量越少。

1.3.2 B-树的性质

M阶B树有有以下性质:

1)根节点最少拥有两棵子树。

2)非根节点关键字个数n满足:ceil(m/2) -1<= n <= m-1; (ceil表示向上取整)。

3)有n棵子树的分支节点则一定存在n-1个关键字。关键字按照递增顺序进行排序。(n>0)

4)所有的叶子节点都在同一层。

B树的节点上存储了数值及指向子树的指针。

1.3.3 B树的插入与删除

B树在插入与删除过程中,需要保持一直它的性质。在这过程中破坏B树结构的主要因素是:节点的关键字数量不符合要求。

插入时先插入,后调整。

1

根据要插入的key值,找到叶子节点并插入。

2

判断当前节点的关键字个数是否满足要求,满足则操作结束,否则进行下一步。

3

以节点中间的key为中心分裂成左右两部分,然后将中间的key插入到父节点中,这个key的左子树指向分裂后的左部分,右子树指向分裂后的右部分。如果key所在的节点关键字不符合要求,则在这个节点上继续执行这一步。

表 B树的插入步骤

图 3阶级B树插入9

删除时分为两步:

1)查找并确定位置,并删除关键字,这一步有两种情况。

a)是叶子节点,则直接删除。

b)非叶子节点,需要用该关键字的后继关键字来填充该关键字,转化为在叶子节点删除一个关键字。后继关键字是其左子树最大的键值或右子树最小的键值。

2)调整B树以维持B树性质。

a)如果缺少节点的右邻兄弟存在且拥有多余的键,则左旋。

b)如果缺少节点的左邻兄弟存在且拥有多余的键,则右旋。

c)左右都没有多余的键,则将它与一个相邻兄弟节点以及父节点中它们的分隔值合并。如果B树失衡,则重新平衡父节点。

图 3阶B树删除14(删除阶段非叶子节点,9和22是后继节点)

图 3阶B树删除9(缺少节点的右邻兄弟存在多余键)

图 3阶B树删除14(合并节点后B树失衡)

1.3.4 B树的优缺点

优点:B树可以不要像平衡树那样频繁的重新保持平衡,同时树的高度远远低于平衡树,这样查询效率就能提高。

缺点:B树可能会没有完全填充,会浪费一些空间。B树也不适合范围查询(比如要查询6-12之间的值)。

2 B+树

对,这个读作B加树。M阶B+树有以下的性质:

1)根节点至少有一个关键字。

2)非根节点关键字数量n满足 ceil(m/2) <= n <= m。

3)有n个关键字必须有n个子女。

4)所有叶子节点在同一层,并且不包含任何信息(可看成是外部节点或查找失败的节点)。

5)关键字自小到大排列。

B+树的节点类型有两种,即内部节点(也叫索引节点)和叶子节点。内部节点不保存数据,只用于索引。

2.1 B+树的插入

插入操作全部在叶子节点上进行,且不能破坏关键字自小到大的顺序。B树的插入分四种情况:

1)被插入关键字所在节点,其关键字数目小于m,并且被插入值小等于该节点最大值,则直接插入。

2)被插入关键字所在节点,其关键字数目小于m,但是被插入值大于该节点最大值,则修正从根节点到当前节点到所有索引值,然后再进行插入。

3)被插入关键字所在节点,其关键字数目等于m,则将此节点分裂为左右两部分,中间的关键字放到父节点中。放入后如果父节点关键字数量小等于m,则操作完成,否则继续分离父节点。

图 3阶B+树插入55的过程

2.2 B+树的删除

B+树的删除与B树的删除算法有些类似。分为两种情况:

1)删除后节点关键字个数>=ceil(m/2)。

a) 如果被删除元素非索引值,则直接删除。

b)是索引值,则将该节点的索引值替换成被删除元素前一个元素,然后再删除。

2)删除后节点关键字个数<ceil(m/2)。

a)相邻兄弟节点有多余关键字,则删除后从其兄弟节点借一个关键字。

b)相邻兄弟节点没有多余关键字,则被删除其他痛其兄弟节点进行合并。(合并后如果破坏了B+树结构,则需要按B+树的性质进行修正。)

图 3阶B+树删除8的过程

2.3 B+树的优缺点

优点:与B 树一样不要频繁的维护其平衡,非常便于范围查找。

缺点:在插入及删除元素的过程中,所做的操作比较多。同时其叶子节点存储了相关的指针,也加大了整个的内存。

3 B+树索引

3.1 联合索引

mysql建立联合索引只会建立一棵B+树。与单值索引,其关键字多了几列(索引项)。排序时,先按照第一列排序,如果相等则按照下一列排序…依此类推。

3.2 MongoDB为什么使用B树作为底层结构

作为非关系型数据库,它对于遍历数据单需求没那么强,它追求的是查询单个记录的性能。

多数使用场景是读多写少。在MongoDB中单个数据查询需求比变量数据更常见。由于B树的非叶子节点也可以存储数据,所以查询一条数据所需的平均随机I/O次数也会比B+树少。这样查询速度也会更快。

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

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

相关文章

C++中的返回值优化(RVO)

一、命名返回值优化&#xff08;NRVO&#xff09; 是Visual C2005及之后版本支持的优化。 具体来说&#xff0c;就是一个函数的返回值如果是一个对象。那么&#xff0c;正常的返回语句的执行过程是&#xff0c;把这个对象从当前函数的局部作用域&#xff0c;或者叫当前函数的…

vue+element弹窗内---下拉框定位问题解决(方法之一)

问题: 加了 :popper-append-to-body"false" 这个属性也不好用时 可以试试这个 解决: 第一步: 找到el-select标签添加(popper-class"popperClass")属性-----如下图 第二步:在css中添加如下代码即可 ::v-deep .popperClass{ top:auto !important; }

Java学习苦旅(二十二)——MapSet

本篇博客将详细讲解Map和Set。 文章目录 搜索概念模型 MapMap.Entry<K, V>Map的常用方法说明TreeMap和HashMap的区别 Set常用方法说明TreeSet和HashSet的区别 结尾 搜索 概念 Map和set是一种专门用来进行搜索的容器或者数据结构&#xff0c;其搜索的效率与其具体的实例…

【win11 绕过TPM CPU硬件限制安装】

Qt编程指南 VX&#xff1a;hao541022348 ■ 下载iso文件■ 右键文件点击装载出现如下问题■ 绕过TPM CPU硬件限制安装方法■ 虚拟机安装win11 ■ 下载iso文件 选择Windows11 &#xff08;multi-edition ISO&#xff09;在选择中文 ■ 右键文件点击装载出现如下问题 ■ 绕过T…

Socks5代理ip和Https代理ip的区别,该如何选择?

Socks5代理和HTTPS代理都是计算机网络中的代理服务器&#xff0c;它们可以用于在客户端和其他服务器之间建立连接并充当中间人。 两种代理类型都有其优缺点和适用场景。 一、什么是Socks5代理 Socks5代理Socks5代理是一个网络协议&#xff0c;通过该协议可以建立TCP和UDP连接…

RDD算子——转换操作(Transformations )【map、flatMap、reduceByKey】

一、map map 算子 # spark-shell sc.parallelize(Seq(1, 2, 3)).map( num > num * 10).collect()# IDEA Test def mapTest(): Unit {// 1. 创建RDDval rdd1 sc.parallelize(Seq(1, 2, 3))// 2. 执行 map 操作val rdd2 rdd1.map(item > item * 10)// 3. 得到结果val re…

在Kubernetes中优雅地导出和清理Ingress资源

引言 Kubernetes的Ingress资源是定义外部访问集群服务的规则。随着微服务架构和容器化技术的普及&#xff0c;Ingress作为路由流量的关键组件变得愈发重要。当我们需要在环境之间迁移Ingress资源或者备份当前的配置时&#xff0c;就会用到导出功能。然而&#xff0c;直接使用k…

已解决 ValueError: Setting an array element with a sequence. 问题

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通Golang》…

Mac 环境多JDK安装与切换

一、下载jdk 去Oracle官网上下载想要安装的jdk版本&#xff0c;M芯片选择arm架构的.bmg格式的文件。 https://www.oracle.com/java/technologies/downloads/。 二、安装jdk 2.1 双击下载的文件&#xff0c;安装步骤一步步点继续就好。 2.2 安装完成后会在/Library/Java/JavaV…

Java网络爬虫--概述与原理

目录标题 基本概念与原理爬虫与搜索系统的关系爬虫运行原理爬虫步骤DNS域名解析 爬虫开发本质网络爬虫的分类通用网络爬虫聚集网络爬虫增量式网络爬虫Deep Web爬虫 参考文献 基本概念与原理 爬虫又叫网络蜘蛛&#xff0c;一种运行在互联网上用来获取数据的自动程序。 互联网的…

高级鉴权网关设计二:SM2国密+协议SPI可扩展+动态配置

​ 上一篇文章是定义切面来做鉴权&#xff0c;针对接口时使用比较方便&#xff0c;还有一种是网关的鉴权如何处理&#xff1f;下面为大家介绍一种比较常用的方案&#xff0c;附带可扩展设计 ​ 既然是网关其实就是和外部的礼尚往来&#xff0c;每个第三方还有可能不一样&#…

2.5 KERNEL FUNCTIONS AND THREADING

我们现在准备讨论更多关于CUDA内核功能以及启动这些内核功能的效果。在CUDA中&#xff0c;内核函数指定所有线程在并行阶段执行的代码。由于所有这些线程执行相同的代码&#xff0c;CUDA编程是众所周知的单程序多数据&#xff08;SPMD&#xff09;[Ata 1998]并行编程风格的实例…

Matlab绘制动态心形线

1. 代码 for alpha0:0.1:30 x-1.8:0.001:1.8; y(x.^2).^(1/3)0.9*(3.3-x.^2).^(1/2).*sin(alpha*pi*x); plot(x,y,r-,LineWidth,1.2); set(gca,YGrid,on); axis([-3,3,-2,4]); text(-2,3.35,$f(x)x^{\frac{2}{3}}0.9(3.3-x^2)^{\frac{1}{2}}sin(\alpha\pi x)$,Interpreter,lat…

如何在整个项目中有效管理成本?

在项目管理方面&#xff0c;没有什么比控制成本更重要。尤其是在项目复杂的情况下&#xff0c;开支可能会让项目成本比预期飙升得更快。项目经理需要采取积极主动的成本管理方法&#xff0c;以保证预算不超支。 项目成本管理的各个阶段 管理项目成本需要在整个项目周期中保持…

【Docker】部署mysql 和 tomcat

目录 部署MySQL 1.搜索镜像 2. 拉取镜像 部署Tomcat 1. 搜索镜像 2.拉取镜像 3.查看镜像 部署MySQL 1.搜索镜像 docker search mysql 2. 拉取镜像 通过mysql 镜像创建对应的容器&#xff0c;并设置端口映射&#xff0c;目录映射 创建mysql 的目录 docker run -id \ …

DataGrip 数据库备份

一、备份 1、找到需要被备份的数据库demo&#xff0c;右键>Import/Export>Export with mysqldump 2、配置路径 点击run&#xff0c;等待完成 导出成功 二、还原 选择 需要导入的数据库>右键>Import/Export>Restore with ‘mysql’ 点击run&#xff0c;刷…

【Python从入门到进阶】46、58同城Scrapy项目案例介绍

接上篇《45、Scrapy框架核心组件介绍》 上一篇我们学习了Scrapy框架的核心组件的使用。本篇我们进入实战第一篇&#xff0c;以58同城的Scrapy项目案例&#xff0c;结合实际再次巩固一下项目结构以及代码逻辑的用法。 一、案例网站介绍 58同城是一个生活服务类平台&#xff0c…

Elasticsearch:Search tutorial - 使用 Python 进行搜索 (三)

这个是继上一篇文章 “Elasticsearch&#xff1a;Serarch tutorial - 使用 Python 进行搜索 &#xff08;二&#xff09;” 的续篇。在今天的文章中&#xff0c;本节将向你介绍一种不同的搜索方式&#xff0c;利用机器学习 (ML) 技术来解释含义和上下文。 向量搜索 嵌入 (embed…

文件系统与日志分析

一&#xff0c;文件系统 &#xff08;一&#xff09;inode 和block概述 1&#xff0c;文件数据包括元信息与实际数据 2&#xff0c;文件存储在硬盘上&#xff0c;硬盘最小存储单位是“扇区”&#xff0c;每个扇区存储512字节 3&#xff0c;block (块) 连续的八个扇区组成一…

OCP NVME SSD规范解读-5.命令超时限制

在"4.7 Command Timeout"章节中&#xff0c;详细定义了NVMe命令的超时要求和限制。 CTO-1&#xff1a;NVMe管理命令和TCG&#xff08;可信计算组&#xff09;命令从提交到完成不应超过10秒&#xff0c;且没有其他命令未完成&#xff08;QD1&#xff09;。CTO-1不适用…