← 返回题目列表

B+ 树节点页内部是如何查找 key 的?为什么页内通常还要二分?

中等 第 19 / 25 题 更新于 2026/07/30
B+树页结构二分查找磁盘IO

简化版

B+ 树先通过树层级定位到某个页,页内部还存着多个有序 key。进入页后需要在这些 key 中找到分支位置或记录位置,常见做法是页内二分查找;因为页已经在内存里,页内 CPU 比较成本远低于磁盘 I/O。

详细版

B+ 树节点不是只存一个 key,而是一个页里存很多 key 和指针。查找流程一般是:

  1. 从根页开始;
  2. 在当前页内部的 key 数组里查找目标 key 应该落在哪个槽位;
  3. 如果是内部页,沿对应子指针到下一层;
  4. 如果是叶子页,在页内定位具体记录或判断不存在。

页内 key 有序,可以线性扫,也可以二分。扇出较大时二分比较次数更少,例如 256 个 key 线性最坏 256 次,二分约 8 次。实际数据库页结构还涉及槽目录、变长记录、前缀压缩等,逻辑上仍是在页内有序定位。

完整版教学

一、B+ 树查找不是只在树层面发生

很多人理解 B+ 树时只画根、内部节点、叶子节点,却忽略每个节点实际是一个磁盘页或内存页。一个页里通常包含很多 key、指针或记录。树层面决定访问哪几个页,页内部还要决定落在哪个槽位。

因此一次查询有两层查找:页间从根到叶,页内在有序 key 中定位。B+ 树高度低,是因为每页扇出大;页内查找快,是因为页读进内存后 CPU 比较很便宜。

记忆钩子:B+ 树查找像进图书馆:先按楼层和书架找页,再在这一页目录里找具体位置。

二、页内为什么可以二分

内部页中的分隔 key 是有序的,叶子页中的索引项也按 key 有序。只要有序,就可以二分查找目标 key 的第一个大于等于位置,或找到应走的子指针区间。

例如页内 key:

[10, 20, 35, 50, 80]
查 42 -> 落在 35 和 50 之间,走对应 child
查 20 -> 命中分隔点或定位到对应范围

若页内有 255 个 key,二分最多约 ceil(log2(255))=8 次比较。相对一次随机磁盘 I/O 的微秒到毫秒级成本,这点 CPU 成本很小。

三、内部页和叶子页查找有什么区别

内部页查找的目标是找到子指针,叶子页查找的目标是找到记录或记录范围起点。内部页的 key 常作为分隔符,不一定保存完整行;叶子页才保存索引项或数据行。

页类型页内查找目标找到后做什么
根页子指针槽位进入下一层
内部页子指针槽位继续向下
叶子页记录或范围起点返回、扫描或回表

这也是为什么范围查询定位到叶子页后,可以沿叶子链表继续扫,而不必反复回到父节点。

四、页内线性扫一定不好吗

不一定。虽然二分比较次数少,但数据库实现会考虑 CPU 缓存、分支预测、key 压缩、槽目录结构等因素。对于很小的页内数组,线性扫描可能因为顺序访问和代码简单而表现不错。对于较大的页内 key 集,二分或变体通常更合适。

这个问题的面试重点不是背某个数据库一定用二分,而是知道「B+ 树节点页内部还有有序查找」。不同系统可能在线性、二分、插值、SIMD 比较之间做工程取舍。

五、页目录和变长记录带来的复杂度

真实页里记录可能是变长的,不一定像数组那样紧密固定长度。数据库常用槽目录保存记录偏移,槽位有序,二分查的是槽目录,再根据偏移找到具体记录。这样即使记录物理位置因为插入删除产生碎片,逻辑顺序仍能维持。

Page
records area: 变长记录实际内容
slot directory: [offset(key10), offset(key20), offset(key35)]

这说明「页内二分」是逻辑模型,落地实现会多一层页目录抽象。

六、页内查找和 B+ 树高度的关系

B+ 树把大量 key 放进一个页,换来高扇出和低高度。高度低减少 I/O 次数,页内查找增加 CPU 比较次数。这个交换非常划算,因为磁盘或缓存未命中的页访问远比内存内比较贵。

假设一棵三层 B+ 树,每层一次页访问,可能只需 3 次页读取定位到叶子。如果每个页内二分 8 次,合计 24 次比较。与减少一层树高带来的 I/O 节省相比,这些比较通常很便宜。

七、常见误区与追问

  • 误区:B+ 树每个节点只有一个 key。 数据库里的节点通常是页,一个页有很多 key。
  • 追问:页内为什么还能二分? 页内 key 或槽目录按 key 有序,满足二分前提。
  • 误区:B+ 树查找复杂度只看树高。 树高决定页访问次数,页内定位也有 CPU 成本。
  • 追问:内部页查找和叶子页查找有什么不同? 内部页找子指针,叶子页找记录或扫描起点。
  • 误区:二分永远比线性扫快。 小数组、缓存和分支因素可能让实现做不同取舍。

八、加强记忆

B+ 树查找要分成「页间」和「页内」。页间沿根到叶减少 I/O,页内在有序 key 或槽目录里定位位置。页越大扇出越高,树越矮;页内比较多一点,但在内存里很便宜。记住这个层次,就能解释为什么 B+ 树适合磁盘和页缓存,而不是只会背高度低。