MySQL(尤其是 InnoDB 引擎)使用 B+ Tree 来实现索引,而不是普通的 B Tree(也叫 B 树),是因为 B+ Tree 更适合数据库系统的特性,特别是在 磁盘存储、范围查询、IO效率 等方面更优秀。
下面详细解释:
📘 一、什么是 B Tree 和 B+ Tree?
🔷 B Tree(B 树)特性:
-
多路搜索树(不是二叉树),每个节点可以有多个子节点
-
每个节点既存储键值(key)也存储数据(value)
-
所有节点的数据都是分散的(可能在叶子节点,也可能在非叶子节点)
-
查询数据可能在任何层级的节点上
🔶 B+ Tree 特性(MySQL 使用):
-
是 B Tree 的变种
-
只有叶子节点存放数据(value),非叶子节点只存放索引键(key),不存数据
-
叶子节点之间用双向链表连接,支持顺序遍历(范围查询效率极高)
-
所有数据都在叶子层,层级相同,树高更低、结构更稳定
🌳 二、B Tree vs B+ Tree 结构图对比
B Tree 示意图:
[20 | 50]
/ | \
[10] [30] [60]
↑ ↑ ↑
数据 数据 数据
B+ Tree 示意图:
[20 | 50] ← 非叶子节点(只存 key)
/ | \
[10] [30] [60] ← 叶子节点(存 key 和 data)
↔ ↔ ↔ ← 叶子节点之间双向链表
👉 所有数据都在叶子节点,层级统一,支持高效范围扫描
🚀 三、MySQL/InnoDB 使用 B+ Tree 的优势
✅ 1. 更高的磁盘 IO 性能
-
MySQL 数据大多存储在磁盘上,访问数据靠**页(Page)**单位读取
-
B+ Tree 非叶子节点只存 key,能在一个页中存储更多的键
-
更扁平的树结构,树的高度低(一般 3~4 层)
-
查询时磁盘 IO 次数少,效率高
✅ 2. 支持高效范围查询和排序
-
B+ Tree 的叶子节点通过链表连接,天然支持范围查询和排序
-
如:
SELECT * FROM users WHERE id BETWEEN 1000 AND 2000;
- 遍历叶子节点链表即可,非常高效
👉 而 B Tree 由于数据分散在各层,无法顺序遍历
✅ 3. 更稳定的查询性能
-
所有数据都在叶子节点,查询路径一致
-
不像 B Tree,数据可能在中间节点,访问路径不确定
✅ 4. 更高的空间利用率
-
非叶子节点只存 key,不存 value,能塞更多 key
-
在相同内存/磁盘页大小下,B+ Tree 的分支因子更高,树高更低
📦 四、举例说明 B+ Tree 如何工作
假设我们有一张用户表 users(id, name),主键 id 是自增的。
插入过程:
-
id=1插入叶子节点 A -
id=2,3,4...插入同一个页,直到满 -
页满后,B+ Tree 会自动分裂节点,把 key 提升到上层索引节点
最终形成一个多层结构,每层只存 key,叶子节点存数据,叶子间有链表连接。
🧠 五、为什么 MySQL 不使用 Hash 索引 或 B Tree?
| 结构 | 是否排序 | 支持范围查询 | 适合场景 | 缺点 |
|---|---|---|---|---|
| Hash | ❌ 否 | ❌ 否 | 等值查询 | 不支持范围/排序 |
| B Tree | ✅ 是 | ✅ 是 | 查询较少 | 查询路径不统一 |
| B+ Tree | ✅ 是 | ✅ 是 | ✅ 查询+范围 | 适合数据库系统 |
所以 B+ Tree 是最适合数据库系统的通用索引结构。
🧪 六、MySQL B+ Tree 性能示意
假设每个节点最多能存放 1000 个键,树高为 3,B+ Tree 能索引的记录数为:
记录数 ≈ 1000 × 1000 × 1000 = 10 亿条
查找任意一条记录只需要 3 次磁盘 IO,非常高效。
✅ 总结
| 对比项 | B Tree | B+ Tree(MySQL 采用) |
|---|---|---|
| 数据存储位置 | 所有节点都存数据 | 只在叶子节点存数据 |
| 查询效率 | 层级不一致,IO 次数不稳定 | 查询路径统一,IO 次数更少 |
| 范围查询 | 不方便 | 叶子节点链表,支持快速范围扫描 |
| 排序能力 | 无 | 天生支持排序 |
| 分支因子 | 相对较小 | 更高,树高更低 |
👉 B+ Tree 是数据库中最经典的索引结构,MySQL/InnoDB 选用它是综合性能、空间、查询效率等权衡后的最佳选择。
2564

被折叠的 条评论
为什么被折叠?



