在 InnoDB 存储引擎 中,数据页(Page)是数据存储的基本单位,而 B+ 树是 InnoDB 用于索引组织的数据结构。
两者的结合,使得 MySQL 能够高效地管理和检索数据。
1. InnoDB 的数据页
1.1 什么是数据页?
数据页(Page)是 InnoDB 存储数据的基本单位,每个数据页大小通常为 16KB(可通过
innodb_page_size
调整)。MySQL 读写数据的最小单位是 16KB,即:
一次磁盘读取最少 16KB(即使查询一行)。
数据修改后,最小的刷盘单位也是 16KB。
1.2 数据页的结构
每个 数据页(16KB) 包含 多个数据行,存储格式如下:
+--------------------+
| 页头(Page Header)| 组织管理信息
+--------------------+
| 记录目录 | 用于快速定位数据
+--------------------+
| 用户数据 | 实际存储的行记录
+--------------------+
| 页目录 | 记录行数据的偏移量
+--------------------+
| 页尾(Page Trailer)| 用于校验完整性
+--------------------+
✅ 每个数据页存储多个行数据,但如果一行数据 过大,可能会溢出到其他页(LOB 大对象存储)。
2. B+ 树与数据页的关系
B+ 树(B+ Tree)是 InnoDB 组织索引的方式,索引节点和数据页直接相关:
B+ 树的每个节点对应一个数据页。
B+ 树的非叶子节点存储索引(主键 + 指向子节点的指针)。
B+ 树的叶子节点存储实际数据,叶子节点之间通过双向链表连接。
2.1 聚簇索引(Clustered Index)
在 InnoDB 中,表的数据是按照主键顺序存储的,因此 数据页的组织方式 直接由 B+ 树的结构 决定。
B+ 树结构
[100 200 300] ← 非叶子节点(索引)
/ | \
[1-99] [100-199] [200-299] ← 叶子节点(数据页)
非叶子节点存储主键和指向子节点的指针。
叶子节点存储数据页,每个页 16KB,包含多行数据。
✅ 查找数据时,从根节点开始,逐层遍历,最终到达叶子节点的数据页。
2.2 B+ 树的层级与数据页
假设数据页大小 16KB,每行数据 1KB
一个数据页 ≈ 16 行数据。
一个非叶子节点存储 100 个索引项。
总数据量 100 万行,B+ 树的层级如下:
第 1 层(根节点):存储 100 个索引项。
第 2 层(中间节点):存储 10,000 个索引项。
第 3 层(叶子节点):实际存储数据页,共 100,000 页。
✅ 一般 3~4 层的 B+ 树就能索引百万级数据,查询性能高效。
3. InnoDB 如何利用 B+ 树与数据页?
3.1 插入数据
找到合适的叶子节点(数据页):
通过 B+ 树索引 定位 主键范围对应的数据页。
插入数据
如果 当前数据页有空位,直接插入。
如果 数据页满了,则 触发页分裂:
创建新数据页,将部分数据迁移,更新 B+ 树索引。
✅ 页分裂会增加 B+ 树的高度,导致查询效率下降,影响写入性能。
3.2 查询数据
从 B+ 树根节点开始,按主键范围遍历索引。
找到目标叶子节点,访问数据页,读取数据行。
如果是范围查询(BETWEEN、ORDER BY),则利用 叶子节点的双向链表 顺序扫描。
✅ B+ 树保证了查询只需访问很少的磁盘页,提高查询效率。
3.3 删除数据
找到数据页,删除行数据。
如果数据页剩余数据过少,可能触发页合并:
将数据合并到相邻页,减少磁盘空间浪费。
✅ 页合并可以减少 B+ 树的高度,提高查询性能。