一、一句话总结
B 树:每个节点都存数据
B+ 树:内部节点只存索引,叶子节点存所有数据 + 链表
二、核心对比表(面试必背)
| 对比项 | B 树 | B+ 树 |
|---|---|---|
| 数据存储位置 | 内部节点 + 叶子节点 | 只在叶子节点 |
| 内部节点 | 存 key + 数据 | 只存 key |
| 叶子节点结构 | 只存数据 | 数据 + 指向下一叶子的指针 |
| 叶子节点链表 | ❌ 无 | ✅ 有(范围查询快) |
| 树的高度 | 较高(内部节点占空间) | 更矮(内部节点能装更多 key) |
| 典型应用 | 嵌入式数据库、早期文件系统 | MySQL InnoDB、大型数据库 |
三、为什么数据库用 B+ 树?
| 优势 | 解释 |
|---|---|
| I/O 更少 | 内部节点只存 key,树更矮 |
| 范围查询快 | 叶子节点链表,顺序访问 |
| 数据集中 | 所有数据在叶子,缓存更高效 |
四、什么时候用 B 树?
- 数据量较小(可放内存)
- 嵌入式系统(SQLite)
- 不需要频繁范围查询
- 实现简单
五、B+ 树叶子节点存什么?
| 索引类型 | 叶子节点内容 |
|---|---|
| 聚簇索引(主键) | 完整数据行 |
| 二级索引 | 索引列 + 主键(回表) |
换个说法:存的是索引+映射(指向数据记录的指针)
六、什么是页分裂 / 页合并?
- 页分裂:节点插入满时,拆成两个节点,父节点增加一个 key
- 页合并:删除后节点太"空",和兄弟合并,父节点减少一个 key
七、时间复杂度
- B / B+ 树:O(log_m N)
- m 很大(如 1000),树高通常 3~4
- 红黑树(内存):O(log₂ N)
八、面试必问模拟题
Q:为什么不用红黑树做数据库索引?
红黑树树高 ≈ log₂ N(千万级数据约 24 次 I/O)
B+ 树树高 ≈ log_m N(m≈1000 时约 3 次 I/O)
磁盘 I/O 是瓶颈,B+ 树少几十倍。
九、一张图帮你记忆(你可以自己画)
text
B 树:
[20, 40]
/ | \
[10] [30] [50, 60]
B+ 树:
[20, 40]
/ | \
[10] [30] [50, 60] ← 内部节点无数据
↓ ↓ ↓
数据 数据 数据 ← 叶子节点存数据 + 链表
十、总结一句话
B 树:全能但中庸
B+ 树:为磁盘和范围查询而生