B+树索引及其原理

 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+树少。这样查询速度也会更快。

相关推荐

  1. B+索引

    2024-01-08 03:34:01       33 阅读
  2. BB+索引、联合索引

    2024-01-08 03:34:01       10 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-08 03:34:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-08 03:34:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-08 03:34:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-08 03:34:01       20 阅读

热门阅读

  1. 【深度学习在时序数据异常检测中的创新】

    2024-01-08 03:34:01       30 阅读
  2. tyxsspa/AnyText 阿里生成文字

    2024-01-08 03:34:01       35 阅读
  3. unittest框架管理测试用例

    2024-01-08 03:34:01       33 阅读
  4. Iceberg: 列式读取Parquet数据

    2024-01-08 03:34:01       47 阅读
  5. 阿里云服务器CPU内存配置怎么选择?

    2024-01-08 03:34:01       65 阅读
  6. 何为算法之什么是算法

    2024-01-08 03:34:01       30 阅读
  7. 【Spring Boot 3】【Flyway】数据库版本管理

    2024-01-08 03:34:01       39 阅读
  8. 【Docker】desktop docker 打包镜像 docker如何打包镜像

    2024-01-08 03:34:01       35 阅读