MySQL 之所以选择 B+ 树 作为其索引结构,而不是红黑树、AVL 树或普通的 B 树等数据结构,主要是因为:
📌 一、为什么不用红黑树 / AVL 树?
✅ 红黑树和 AVL 树的特点:
- 都是 自平衡二叉查找树。
- 查找效率为
O(log n)。 - 每个节点只存储一个键值。
❌ 不适合数据库的磁盘 I/O 特性:
-
树的高度过高(I/O 次数多)
- 假设每个节点只有一个键值,100 万条数据的红黑树高度大约是 20 层。
- 每次查询可能需要进行 20 次磁盘 I/O。
- 磁盘 I/O 是性能瓶颈,速度远远低于内存操作。
-
不支持范围查询
- 红黑树、AVL 树只能进行点查询(精确匹配),不能高效地进行范围查询(如
WHERE id > 100)。
- 红黑树、AVL 树只能进行点查询(精确匹配),不能高效地进行范围查询(如
-
不适合块设备存储
- 数据库是以页(Page)为单位从磁盘读取数据的,通常一页是 16KB。
- 红黑树无法利用这种“一次读取多个连续键”的特性。
📌 二、为什么不用普通的 B 树?
✅ B 树的优点:
- 支持高效的查找、插入和删除。
- 每个节点可以包含多个键值。
- 树的高度较低,减少了磁盘 I/O 次数。
❌ B 树的缺点(相对于 B+ 树):
-
非叶子节点也存储数据(data)
- 导致每个节点能存储的键值减少,从而增加树的高度。
- 占用更多磁盘空间。
-
不便于范围查询
- 虽然 B 树也能做范围查询,但没有 B+ 树那样高效。
- 因为 B 树的叶子节点不是顺序链接的。
📌 三、为什么选择 B+ 树?
✅ B+ 树的核心优势:
| 特性 | 描述 |
|---|---|
| ✅ 所有数据都在叶子节点 | 非叶子节点仅用于索引,提高扇出(fanout),降低树高。 |
| ✅ 叶子节点之间用链表连接 | 高效支持范围查询(range query)。 |
| ✅ 更少的磁盘 I/O | 每次加载一个页能获取更多索引项,减少访问次数。 |
| ✅ 平衡性好 | 插入/删除操作后仍然保持平衡,保证查询效率稳定。 |
🧮 示例:
假设:
- 一个磁盘页大小为 16KB;
- 每个键值占 8 字节,指针占 6 字节;
- 每个节点最多可容纳
(16 * 1024) / (8 + 6)≈ 1170 个键值;
那么:
- 三层 B+ 树可以存储的数据量:
1170^3 - 查询只需要最多 3 次磁盘 I/O!
📌 四、总结
| 数据结构 | 是否适合数据库索引 | 原因 |
|---|---|---|
| 红黑树 / AVL 树 | ❌ 不适合 | 树高、不支持范围查询、不适合磁盘 I/O |
| B 树 | ⚠️ 部分适合 | 支持磁盘 I/O,但数据分散、范围查询不如 B+ 树 |
| B+ 树 | ✅ 最佳选择 | 数据集中在叶子节点、支持范围查询、适合磁盘分页机制 |
🧠 补充:InnoDB 中的 B+ 树
- InnoDB 使用的是聚簇索引(Clustered Index):
- 主键索引的叶子节点直接存储整行数据。
- 辅助索引(Secondary Index)的叶子节点存储主键值,再回表查询。
✅ 总结一句话:
MySQL 使用 B+ 树作为索引结构,是因为它在磁盘 I/O 效率、范围查询、树高度控制等方面具有最优的综合表现,特别适合大规模数据的持久化存储与快速检索。
848

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



