← 返回题目列表

B+ 树页分裂和页合并是怎么发生的?

高频 困难 第 15 / 25 题 更新于 2026/07/29
B+树页分裂页合并索引维护

简化版

B+ 树插入导致叶子页放不下时,会把页拆成两个页,并把分隔 key 插入父节点;如果父节点也满了,分裂会向上传播,甚至让根分裂、树高加 1。删除后页太空时,会先尝试向兄弟页借 key,借不到就合并页,并从父节点删除分隔 key,合并也可能向上传播。

详细版

B+ 树以页为单位存储节点。页分裂发生在插入后节点超过容量时:叶子页分裂时,数据项在两个叶子之间重新分布,并把新页的最小 key 复制到父节点作为导航 key;内部页分裂时,中间 key 通常上推到父节点,左右两边成为两个内部节点。这个差异是高频细节。

页合并发生在删除后节点低于最低占用率时。数据库或教材实现通常先尝试和相邻兄弟重分布,如果兄弟也不富余,再合并两个页,并更新父节点分隔 key。分裂和合并的目的不是让节点“刚好一半”,而是保持节点容量约束、搜索有序性和树高平衡。

完整版教学

一、页为什么会分裂

B+ 树节点通常对应磁盘页或内存页,每页容量有限。假设一个叶子页最多能放 4 个 key,当前页是 [10,20,30,40],再插入 50 就放不下了。此时不能简单扩容当前页,因为页大小固定;B+ 树的做法是分裂成两个叶子页,并把新页接入叶子链表。

before insert 50:
  [10,20,30,40]

after split:
  [10,20,30] -> [40,50]

分裂的本质是把一个溢出的页拆成两个合法页,同时让父节点知道右侧新页从哪个 key 开始。

二、叶子页分裂为什么是 copy up

B+ 树叶子页存放真实数据项,父节点只做导航。因此叶子页分裂后,父节点中插入的是右侧新叶子的最小 key 的副本,而这个 key 仍然保留在叶子页中。这个过程常叫 copy up。

leaf split:

leaf1: [10,20,30]
leaf2: [40,50]
parent receives separator: 40

parent key 40 是导航副本,leaf2 里仍然有 40

这和普通 B 树或 B+ 树内部节点分裂的“中间 key 上推”不同。叶子层必须保留完整数据,因为所有查询最终都要在叶子层命中数据项。

三、内部页分裂为什么可能向上传播

如果父节点插入分隔 key 后也满了,父节点也要分裂。内部页分裂时,中间 key 通常被推到更上层,左右两边分别成为两个内部页。若根也分裂,就创建新根,树高增加 1。

分裂位置父节点拿到什么key 是否保留在原节点
叶子页分裂右叶子最小 key 的副本保留在叶子页
内部页分裂中间 key 上推不再留在左右内部页中
根页分裂创建新根树高增加
root full, split:

        [30]
       /    \
 [10,20]  [40,50]

树高从 1 层增加到 2 层

这就是为什么 B+ 树增长通常是“先变宽,必要时变高”。树高增加并不频繁。

四、删除后为什么要借位或合并

删除会让页占用率下降。为了避免大量半空页浪费空间,B+ 树通常规定除根外节点至少保持一定数量的 key。当删除后低于下限时,先看相邻兄弟是否有多余 key;如果有,就重分布,也叫借位;如果没有,就把两个页合并。

最低占用 = 2

delete 30:
  leaf [30,40] -> [40] 低于下限

兄弟 [10,20,25] 有富余:
  借 25 后:
  [10,20] | [25,40]

借位后父节点的分隔 key 也要更新,因为右侧页的最小 key 可能变了。只调整叶子页、不调整父节点,会让后续搜索走错分支。

五、合并也可能向上传播

如果兄弟页没有多余 key,就合并两个页,并从父节点删除对应分隔 key。父节点少了一个 key 后,也可能低于最低占用率,于是合并继续向上传播。极端情况下,根节点只剩一个孩子时,可以把这个孩子提升为新根,树高减 1。

merge leaves:
  [10] + [20] -> [10,20]
  parent 删除分隔 key 20

if parent underflow:
  parent 也要借位或合并

这也是 B+ 树删除比插入更容易写错的原因:不仅要处理当前页,还要维护父节点、兄弟页和叶子链表。

六、常见误区与追问

记忆钩子:插入满了向上分裂,删除空了向旁边借,借不到再合并。

  • 误区:页分裂只发生在叶子节点。 叶子分裂后父节点可能溢出,内部节点和根节点也可能继续分裂。
  • 误区:叶子页分裂时中间 key 被移出叶子。 B+ 树叶子层要保留完整数据项,父节点拿到的是导航副本。
  • 误区:删除后低于下限直接合并。 通常先尝试向兄弟页借位,借不到才合并。
  • 追问:根节点分裂会怎样? 创建新根,树高增加 1;这也是 B+ 树唯一变高的典型路径。
  • 追问:合并会不会让树变矮? 可能,根节点只剩一个孩子时可以压缩根,树高减 1。
  • 追问:分裂和合并为什么影响写性能? 它们会修改多个页和父子指针,还可能引发日志、锁和刷盘成本。

七、加强记忆

B+ 树页分裂和页合并可以按“容量约束”来记:插入让页超上限,就拆成两个页,并把导航 key 交给父节点;删除让页低于下限,就先向兄弟借,借不到再合并,并同步更新父节点。叶子分裂是 copy up,内部分裂是 push up;合并和分裂都可能向上传播。把这几条讲清楚,基本就能覆盖面试对 B+ 树维护过程的追问。