问题

介绍一下InnoDB的数据页,和B+树的关系是什么?

答案

1. 核心概念

数据页(Page) 是InnoDB存储引擎管理磁盘空间的基本单位,默认大小为 16KB。B+树索引是由多个数据页以树形结构组织而成的,每个数据页就是B+树的一个节点。

2. 数据页的结构

一个InnoDB数据页由以下几个部分组成:

+------------------+
| File Header      | (38字节) - 页的通用信息
+------------------+
| Page Header      | (56字节) - 页的专有信息
+------------------+
| Infimum/Supremum | (26字节) - 虚拟行记录
+------------------+
| User Records     | (不定)   - 实际存储的行记录
+------------------+
| Free Space       | (不定)   - 未使用空间
+------------------+
| Page Directory   | (不定)   - 记录的相对位置
+------------------+
| File Trailer     | (8字节)  - 校验页完整性
+------------------+

关键字段说明

  • File Header:包含页号、前后页指针(构成双向链表)、页类型、校验和等
  • Page Header:记录数量、自由空间起始位置、最近插入位置、页的层级等
  • User Records:按主键顺序存储的行记录,通过next_record指针形成单向链表
  • Page Directory:页目录,分组存储记录偏移量,用于二分查找加速

3. 数据页与B+树的关系

3.1 数据页是B+树的节点

  • 非叶子节点页:存储索引键和指向下层页的指针(页号)
  • 叶子节点页:存储完整的行记录(聚簇索引)或主键值(二级索引)

3.2 页之间的连接方式

非叶子节点:
[索引键1|页指针1][索引键2|页指针2]...
         ↓             ↓
    叶子节点页1 ← → 叶子节点页2 ← → 叶子节点页3
  • 纵向:通过页号(指针)连接父子节点
  • 横向:叶子节点通过File Header中的前后页指针形成双向链表,支持范围查询

3.3 树的高度与页的关系

假设一个数据页16KB:

  • 非叶子节点存储:(索引键 + 页号),假设每项14字节,可存储约 1000个索引项
  • 2层B+树:1000 × 1000 = 100万行
  • 3层B+树:1000 × 1000 × 1000 = 10亿行

这意味着大部分表通过2-3层B+树即可满足查询需求。

4. 性能优化考量

4.1 顺序插入 vs 随机插入

  • 顺序插入:数据页按顺序填充,减少页分裂,空间利用率高
  • 随机插入:可能引发频繁的页分裂和页合并,导致碎片

4.2 页的填充因子

  • InnoDB默认保留页空间的 1/16 用于后续更新
  • 可以通过 OPTIMIZE TABLE 重建索引,消除碎片

4.3 预读机制

  • 线性预读:顺序访问连续页面时,预读后续页到Buffer Pool
  • 随机预读:某个区(64个连续页)被频繁访问时,预读整个区

5. 总结

  • 数据页是InnoDB的最小I/O单位(16KB),也是B+树的节点
  • 非叶子节点存索引+指针,叶子节点存完整数据或主键值
  • 页之间通过页号纵向连接,叶子节点通过双向链表横向连接
  • 理解数据页结构有助于优化索引设计,避免页分裂,提高缓存命中率

面试要点:能清晰说明数据页的大小(16KB)、主要组成部分、与B+树的节点对应关系、以及这种设计对查询性能的影响。