索引(B+树)

下面系统性讲一下 B+ 树索引,这是数据库、文件系统中最核心的索引结构之一。


一、什么是 B+ 树索引?

B+ 树(B+ Tree) 是一种多路平衡查找树,专门为磁盘/外存访问优化设计的索引结构。

特点一句话概括:

所有数据都在叶子节点,内部节点只存键用于导航;叶子节点通过链表相连,支持高效范围查询。


二、B+ 树的结构

一棵典型的 B+ 树:

                [ 20 | 40 ]
               /           \
        [10|20]         [30|40]
       /   |   \       /   |   \
 [1,3,5][12,15][18,19][25,28][35,38][45,50]

1. 节点类型

节点类型 存储内容 作用
根节点 key + 指针 查询入口
内部节点 key + 子节点指针 路由导航
叶子节点 key + data(或主键) 真正存放数据

2. 关键特性

  • 多路(m 叉):一个节点可有多于两个孩子
  • 平衡:所有叶子节点在同一层
  • 有序:节点内 key 按大小排序
  • 叶子节点链表:方便范围扫描
  • 内部节点不存真实数据

三、为什么数据库偏爱 B+ 树?

1. 减少磁盘 I/O(最重要)

磁盘读取是按 页(Page,通常 4KB/16KB) 来的:

  • 二叉树:高度高 → I/O 次数多
  • B+ 树:高度低(通常 3~4 层) → 一次查询只需 3~4 次磁盘 I/O

假设:

  • 阶数 m = 100
  • 3 层 B+ 树可存:100^3 ≈ 100 万 条记录

2. 非常适合范围查询

叶子节点之间有双向/单向链表

SELECT * FROM orders WHERE id BETWEEN 100 AND 200;

✅ 定位到 100
✅ 顺着链表一路扫到 200

相比 B 树、哈希索引优势巨大。


3. 查询稳定(O(log n))

无论查哪条数据,路径长度都一样(树高固定)。


四、B+ 树 vs B 树 vs 哈希索引

特性 B+ 树 B 树 哈希索引
数据位置 仅叶子节点 各层都有 Key → Value
范围查询 ✅ 极好 ⚠️ 一般 ❌ 不支持
磁盘友好
查询复杂度 O(log n) O(log n) O(1)
顺序扫描
数据库使用 ✅ 主流 ⚠️ 少 ⚠️ 特定场景

👉 InnoDB 聚簇索引 = B+ 树


五、B+ 树在数据库中的实际应用

1. InnoDB 聚簇索引(Clustered Index)

  • 主键即索引
  • B+ 树的 叶子节点存整行数据
  • 一张表 只有一个聚簇索引
叶子节点:
[ id=1 | name="Tom" | age=18 ]
[ id=2 | name="Jerry" | age=20 ]

2. 二级索引(Secondary Index)

  • 叶子节点存:索引列 + 主键值
  • 回表:通过主键再去聚簇索引查整行数据
二级索引(name):
[name="Tom" | id=1]
→ 再查聚簇索引 id=1

六、B+ 树的插入与分裂(简化版)

  1. 找到目标叶子节点
  2. 插入 key
  3. 若节点满了:
    • 分裂成两个节点
    • 中间 key 上提到父节点
  4. 若根节点分裂 → 树高 +1(很少发生)

✅ 始终保持平衡


七、B+ 树的删除与合并

  • 删除 key
  • 若节点过空:
    • 与兄弟节点合并
    • 或借一个 key
  • 极端情况:树高降低

八、常见面试/实战考点

1. 为什么 B+ 树比红黑树更适合数据库?

  • 红黑树是二叉树 → 高度高 → I/O 多
  • B+ 树是多路树 → 高度低 → 磁盘友好

2. B+ 树一般多高?

  • 通常 3~4 层
  • 千万级数据也能 3 次 I/O 搞定

3. 为什么 MySQL 不用哈希索引做默认?

  • 不支持范围查询
  • 无法排序
  • 冲突处理复杂

九、一句话总结

B+ 树是一种为磁盘设计的多路平衡查找树,所有数据集中在叶子节点,通过层级控制和链表连接,实现了高效的单点查询和卓越的范围查询能力,是现代数据库索引的事实标准。

上一篇
下一篇