B+ 树插入2025年3月17日 | 阅读11分钟 B 树和 B+ 树通常用于实现动态多级索引。然而,B 树用于索引的一个缺点是,它还在 B 树节点中存储了与特定键值对应的(指向包含键值的磁盘文件块的)数据指针。这种方法显著减少了能够装入 B 树节点中的项目数量,这导致 B 级树结构的增加和记录搜索时间的延长。通过仅在树的叶节点存储数据指针,B+ 树消除了上述缺点。 因此,B 树的内部节点和 B+ 树的叶节点具有非常不同的结构。应强调的是,由于数据指针仅存在于叶节点,所有键值及其相应的数据指针必须由叶节点存储,以便能够访问它们。此外,叶节点相互连接以提供对记录的有组织访问。因此,叶节点构成索引的第一级,内部节点是多级索引中的其他级别。 为了仅作为调节记录搜索的媒介,一些叶节点的键值也出现在内部节点中。与 B 树不同,B+ 树有两个阶,“a”和“b”,一个用于内部节点,另一个用于外部(或叶)节点。这一点从上面的描述中可以看出。具有“a”阶的内部 B+ 树具有以下节点结构 - 每个内部节点具有以下结构:其中每个 Ki 是键值对,每个 Pi 是树指针(指向树的另一个节点)(参见图 I)。
- 每个内部节点包含每个搜索字段以下值:K1 < K2 < …. < Kc-1
- 对于 Pi 指针指向的子树中每个搜索字段“X”的值,以下陈述成立:Ki-1 < X <= Ki,其中 1 < i < c,并且 Ki-1 < X。
- 每个内部节点最多包含“a”个树指针。
- 每个内部节点至少有 ceil(a/2) 个树指针,而根节点至少有两个树指针。
- 如果一个内部节点有“c”个指针,则它包含“c-1”个键值,其中 c< = a。
如果按顺序存储值,大多数查询可以更快地处理。然而,期望以排序的顺序一个接一个地存储表的行是不切实际的,因为这样做将需要为添加或删除的每一行重新创建表。 这促使我们考虑将我们的行放入树结构中。我们最初的想法是平衡二叉搜索树,如红黑树,但由于数据库存储在磁盘上,这实际上并没有多大意义。磁盘通过一次读取和写入大量数据来工作;这些块通常为 512 字节或四千字节。二叉搜索树的每个节点仅使用其中的一小部分。 找到一个更整齐地适合磁盘块的结构是有意义的。 这产生了 B+ 树,其中每个节点包含最多 d 个键和最多 d 个指向子节点的引用。每个引用指向一个子树的根,该子树的所有值都介于节点中的两个键之间,因此被认为是“介于”节点中的两个键之间。 这里有一个 d=4 的相对较小的树。  B+ 树的特性- 只有叶节点可以存储数据点。
- 键存在于内部节点中。
- 我们在 B+ 树中使用键进行直接元素搜索。
- 如果有“m”个元素,则至少有“[m/2] -1”个键,最多有“m-1”个键。
- 根节点至少有两个子节点和一个键。
- 除了根节点外,每个节点可以有至少“m/2”个子节点,最多“m”个子节点(对于“m”个元素)。
B+ 树插入在本教程中,您将了解 B+ 树的插入操作。此外,还提供了使用 C、C++、Java 和 Python 示例将成员插入 B+ 树。 向 B+ 树添加元素通常涉及三个基本步骤:找到正确的叶节点、添加元素以及平衡或拆分树。 下面我们详细考察这些情况。 插入操作- 在将元素添加到 B+ 树之前,需要考虑这些特性。
- 根节点至少有两个子节点。
- 除根节点外,每个节点最多允许有 m 个子节点,最少有 m/2 个子节点。
- 每个节点至少有 m/2 - 1 个键,最多有 m - 1 个键。
- 插入元素的步骤如下。
- 转到正确的叶节点,因为每个元素都插入到叶节点中。
- 使用键激活叶节点。
情况 I 如果叶节点未满,则按升序将键插入叶节点。 情况 II - 如果叶节点已满,则按升序将键插入每个叶节点,然后如下平衡树。
- 在 m/2 的位置拆分节点。
- 此外,将 m/2 键添加到父节点。
- 如果父节点已满,请遵循步骤二到三。
示例显示插入后的树。 假设每个 B+ 树节点最多可存储 4 个指针和 3 个键 - m=3(奇数),d=1
- 部分(针对奇数 m 值)
- 具有至少两个 (d+1) 个条目的叶节点
- 具有至少两个 (d+1) 个指针和一个条目的非叶节点
- 插入 1、3、5、7 和 9。
- 插入 1
 - 插入 3、5
 - 插入 7
 - 插入 9

这是最终的 B+ 树。 C++ 程序代码 输出 The size of bucket is 3!
1 2 3
3
1 2 3 4 5
B+ 树的优点- 与具有相同层数的 B 树相比,B+ 树可以在其内部节点中存储更多条目。这强调了每个特定键的搜索时间有了多么大的改进。由于其较低的层数和 Pnext 指针,B+ 树在从驱动器访问记录方面特别快速和有效。
- B+ 树允许数据进行顺序访问和直接访问。
- 要获取记录,需要相同数量的磁盘访问。
- 由于 B+ 树中的冗余搜索键,不可能再次存储搜索键。
B+ 树的缺点按顺序访问键的难度是 B 树的主要缺点。B+ 树仍然具有快速的随机访问。 B+ 树的应用- 多级索引
- 更快的树操作(插入、删除、搜索)
- 数据库索引
B 树与 B+ 树以下是 B 树和 B+ 树之间的一些区别 - 数据和搜索键存储在 B 树的内部节点或叶节点中。但是,数据仅存储在 B+ 树的叶节点中。
- 由于所有数据都位于 B+ 树的叶节点中,因此搜索任何数据都非常简单。在 B 树的叶节点中无法找到数据。
- 数据可以位于 B 树的内部节点或叶节点中。内部节点删除非常困难。数据仅存在于 B+ 树的叶节点中。叶节点删除相对简单,因为可以直接删除。
- B 树的插入比 B+ 树更复杂。
- B+ 树存储冗余搜索键,但 B 树没有冗余值。
- 在 B+ 树中,叶节点数据按顺序链接列表排序,但在 B 树中,叶节点不能使用链表存储。许多数据库系统的实现更倾向于 B+ 树的结构简洁性。
基本区别在于它们如何利用内部存储。 概述B+ 树是一种非线性存储结构,用于存储具有“一对多”关系的数据元素集合,通常用于数据库和操作系统文件系统。 - 非叶节点不存储数据,只存储索引(冗余),可以放置更多索引。
- 叶节点包含所有索引字段。
- 叶节点通过指针链接以提高区间访问性能。
为什么选择 B+ 树?- 由于 MySQL 通常将数据存储在磁盘上,读取数据会产生磁盘 IO 消耗。B+ 树的非叶节点不存储数据。通常,节点的大小设置为磁盘页面大小,因此B+ 树的每个节点可以容纳更多键,并且 B+ 树的高度较低,从而减少了磁盘 IO 消耗。
- B+ 树叶节点形成一个链表,并用于范围搜索和排序。
MySQL 使用 B+ 树作为索引- 由于 MySQL 通常将数据存储在磁盘上,读取数据会产生磁盘 IO 消耗。B+ 树的非叶节点不存储数据,但 B 树的非叶节点会存储数据。通常,节点的大小会设置为磁盘页面大小,以便 B+ 树的每个节点可以容纳更多键,而 B 树的键较少。因此,B 树的高度将高于 B+ 树,这将导致更多的磁盘 IO 消耗。
- B+ 树叶节点形成一个链表,并用于范围搜索和排序。B 树的范围搜索和排序需要递归遍历树。
|