B树与B+树详解及其在MySQL中的应用
B树与B+树详解及其在MySQL中的应用
一、B树(B-Tree)基础
1.1 B树的定义与特点
B树是一种自平衡的树,它保持数据有序,并允许在对数时间内进行插入、删除和查找操作。其主要特点包括:
- 每个节点最多包含m个子节点(m阶B树)
- 除根节点和叶子节点外,每个节点至少有⌈m/2⌉个子节点
- 所有叶子节点都在同一层
- 每个节点都存储键值信息
- 节点的键值从左到右递增排列
1.2 B树的应用场景
B树特别适合于磁盘等外部存储设备的存储:
- 减少磁盘I/O次数
- 支持对数时间的查找
- 适合文件系统的实现
二、B+树详解
2.1 B+树的结构特点
B+树是B树的一种变体,具有以下特点:
- 非叶子节点只存储键值信息,不存储数据
- 所有数据都存储在叶子节点
- 叶子节点通过指针相连,形成有序链表
- 所有叶子节点具有相同的深度
- 叶子节点包含了所有的键值信息,且按序排列
2.2 B+树的优势
相比B树,B+树具有以下优势:
-
更高的查询性能
- 非叶子节点不存储数据,一个节点可以存储更多键值
- 树的高度更低,减少I/O次数
-
范围查询更高效
- 叶子节点相连,方便范围查询
- 无需中序遍历整棵树
-
更稳定的查询效率
- 所有查询都要到叶子节点,查询路径长度相同
- 查询性能更加稳定
三、为什么MySQL选择B+树作为默认索引
3.1 主要原因
-
更适合磁盘存储
- B+树非叶子节点不存储数据,一个节点可以存储更多的键值
- 显著减少树的高度,降低磁盘I/O次数
-
更高效的范围查询
- 叶子节点通过指针相连,范围查询只需要遍历叶子节点
- 大大提高范围查询的性能
-
更好的缓存效果
- 非叶子节点不存储数据,更容易被缓存
- 缓存命中率更高
3.2 在MySQL中的具体应用
-
InnoDB存储引擎
- 使用B+树作为主键索引和二级索引的实现
- 聚集索引(主键索引)直接存储数据行
- 二级索引的叶子节点存储主键值
-
优化特性
- 支持事务的ACID特性
- 支持MVCC(多版本并发控制)
- 支持行级锁
四、B树与B+树的结构示例
4.1 B树的结构示例
以一个3阶B树为例,演示数据的插入过程。在3阶B树中:
- 每个节点最多可以有3个子节点
- 每个节点最多可以存储2个键值
- 除根节点外,每个节点至少有1个键值
- 所有数据都按顺序排列
让我们通过插入数据[3,1,5,4,2,6,7,8]来展示B树的生长过程:
- 插入3,1,5:
[1,3,5]
- 节点已满,插入4时需要分裂:
[3]
/ \
[1] [4,5]
- 插入2:
[3]
/ \
[1,2] [4,5]
- 插入6:
[3]
/ \
[1,2] [4,5,6]
- 右节点已满,插入7时需要再次分裂:
[3,5]
/ | \
[1,2] [4] [6,7]
- 最终插入8:
[3,5]
/ | \
[1,2] [4] [6,7,8]
这个更详细的示例展示了:
- 节点可以包含1个或2个键值
- 当节点满时(3个键值)会触发分裂
- 分裂后中间值会上升到父节点
- 树在需要时会自动保持平衡
4.2 B+树的结构示例
使用相同的数据[3,1,5,4,2,6,7,8]构建一个3阶B+树,展示其结构特点:
- 初始状态(插入3,1,5):
[1,3,5]
↔
- 插入4后分裂:
[3]
/ \
[1,2,3] [3,4,5]
↔ ↔
- 继续插入2,6:
[3]
/ \
[1,2,3] [3,4,5,6]
↔ ↔
- 插入7,8后的最终状态:
[3,5]
/ | \
[1,2,3] [3,4,5] [5,6,7,8]
↔ ↔ ↔
这个更详细的B+树示例展示了其独特的特点:
- 所有数据都存储在叶子节点中
- 叶子节点通过指针(↔)相连,形成有序链表
- 非叶子节点只存储键值用于索引
- 索引项会在叶子节点中重复出现
- 每个叶子节点可以存储多个数据项
4.3 查询过程示例
- 在B树中查找数据6的过程:
[3,5] ① 从根节点开始,6>5
/ | \
[1,2] [4] [6,7,8] ② 转向右子树,找到数据6
- 在B+树中查找数据6的过程:
[3,5] ① 从根节点开始,6>5
/ | \
[1,2,3] [3,4,5] [5,6,7,8] ② 转向右子树
↔ ↔ ↔ ③ 在叶子节点找到6
- B+树范围查询[4-7]的过程:
[3,5]
/ | \
[1,2,3] [3,4,5] [5,6,7,8] ① 找到4所在的叶子节点
↔ ↔ ↔ ② 通过链表顺序遍历到7
这些更详细的示例清晰地展示了:
- B树可能在非叶子节点就找到目标数据
- B+树所有查询都要到叶子节点,路径长度一致
- B+树的范围查询只需遍历叶子节点链表,无需在树中来回移动
- B+树中相同的键值可能在内部节点和叶子节点中重复出现
五、B树与B+树的主要区别
特性 | B树 | B+树 |
---|---|---|
数据存储位置 | 所有节点都可以存储数据 | 只在叶子节点存储数据 |
键值分布 | 每个节点的键值不重复 | 非叶节点的键值会在叶节点重复 |
查询效率 | 可能在非叶节点结束 | 总是要查询到叶节点 |
范围查询 | 需要中序遍历 | 只需遍历叶子节点链表 |
节点存储 | 键值+数据 | 内部节点存键值,叶节点存数据 |
树的高度 | 相对较高 | 相对较低 |
查询稳定性 | 不稳定 | 稳定 |
五、总结
B+树之所以成为MySQL默认的索引类型,主要得益于其特殊的结构设计:
- 所有数据存储在叶子节点,显著减少了树的高度
- 叶子节点形成有序链表,极大提升了范围查询性能
- 非叶子节点不存储数据,提高了缓存效率
- 查询效率稳定,所有查询都是从根节点到叶子节点的完整路径
这些特性使得B+树特别适合数据库索引的实现,能够提供稳定且高效的查询性能,尤其在大数据量和范围查询场景下表现突出。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 程序员小刘
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果