mysql从零单排之数据页与索引页

3 阅读3分钟

这是一个关于MySQL底层存储结构的技术问题,让我为你详细解答:

数据页和索引页的本质

数据页和索引页既是物理磁盘的管理方式,也是InnoDB内部的逻辑概念,两者并不矛盾,而是不同层次的抽象。


1. 物理层面:磁盘管理方式

┌─────────────────────────────────────┐
│           表空间文件 (.ibd)          │
│  ┌─────────┬─────────┬─────────┐   │
│  │  Page 0 │  Page 1 │  Page 2 │   │  ← 物理上连续的16KB块
│  │ (File   │ (Inode  │ (数据页) │   │
│  │ Header) │ Page)   │         │   │
│  └─────────┴─────────┴─────────┘   │
│        每个Page固定16KB              │
└─────────────────────────────────────┘

物理特征:

  • InnoDB以页(Page)为单位管理磁盘空间,默认16KB
  • 表空间文件(.ibd)由无数个16KB的页组成
  • 页通过**页号(Page Number)**物理定位,是绝对的偏移量
  • 磁盘I/O最小单位就是页,保证原子性

2. 逻辑层面:InnoDB内部概念

┌────────────────────────────────────────┐
│           逻辑页结构 (16KB)             │
│  ┌──────────┬──────────────────────┐  │
│  │ File     │                      │  │
│  │ Header   │    User Records      │  │
│  │ (38字节) │    (实际数据/索引)    │  │
│  ├──────────┤                      │  │
│  │ Page     │                      │  │
│  │ Header   │                      │  │
│  │ (56字节) │                      │  │
│  ├──────────┼──────────────────────┤  │
│  │ Infimum  │ ← 虚拟最小记录        │  │
│  │ Supremum │ ← 虚拟最大记录        │  │
│  ├──────────┼──────────────────────┤  │
│  │ User     │ 行记录1 → 行记录2 → ... │  │
│  │ Records  │ (通过next_record链表)  │  │
│  ├──────────┴──────────────────────┤  │
│  │ Free Space (空闲空间)            │  │
│  ├─────────────────────────────────┤  │
│  │ Page Directory (页目录,加速查找) │  │
│  ├─────────────────────────────────┤  │
│  │ File Trailer (8字节,校验用)     │  │
│  └─────────────────────────────────┘  │

逻辑特征:

  • 页内部有严格的逻辑结构(记录、目录、空闲空间等)
  • 数据页索引页在物理格式上完全相同,只是存储内容不同
  • 通过Page Header中的PAGE_LEVEL等字段标识页类型

3. 数据页 vs 索引页的区别

维度数据页(Leaf Page)索引页(Non-Leaf Page)
存储内容完整的行记录数据索引键值 + 子页指针
PAGE_LEVEL0(叶子层)≥1(非叶子层)
记录格式包含所有列数据仅包含索引列+页号
物理结构完全相同完全相同
在B+树中的位置最底层(双向链表)上层节点
        B+树索引结构示意
        ┌─────────────┐
        │  索引页(L2)  │  ← 根节点,存键值+指针
        │  [10|30|50] │
        └──────┬──────┘
       ┌───────┼───────┐
    ┌──┴──┐ ┌──┴──┐ ┌──┴──┐
    │索引页│ │索引页│ │索引页│  ← 中间层(可能有多层)
    │(L1) │ │(L1) │ │(L1) │
    └──┬──┘ └──┬──┘ └──┬──┘
   ┌───┼───┐ ┌─┼─┐ ┌───┼───┐
┌──┴┐┌─┴┐┌─┴┐│ │ ┌┴┐┌─┴┐┌─┴┐
│数据│数据│数据│...│数据│数据│数据│ ← 叶子节点(数据页)
│页  │页  │页  │   │页  │页  │页  │
└───┘└───┘└───┘   └───┘└───┘└───┘
  ↑ 这些"数据页"也是索引的叶子节点!

4. 关键理解:聚簇索引的特殊性

核心结论:在InnoDB中,数据页和索引页没有绝对界限

  • 聚簇索引的叶子节点 = 数据页(存完整行数据)
  • 二级索引的叶子节点 = 索引页(存索引列+主键值)
  • 非叶子节点统一称为索引页
聚簇索引(主键索引)结构:
┌─────────────────────────────────────────┐
│  非叶子节点(索引页)                    │
│  存储:[主键值, 子节点页号]               │
├─────────────────────────────────────────┤
│  叶子节点(同时也是数据页)               │
│  存储:完整行数据 + 相邻页指针(双向链表)  │
└─────────────────────────────────────────┘

二级索引结构:
┌─────────────────────────────────────────┐
│  非叶子节点(索引页)                    │
│  存储:[索引列值, 子节点页号]             │
├─────────────────────────────────────────┤
│  叶子节点(索引页,不是数据页)           │
│  存储:[索引列值, 主键值] → 需回表查数据   │
└─────────────────────────────────────────┘

5. 总结

问题答案
是物理还是逻辑?两者都是——物理上是磁盘管理单元,逻辑上是InnoDB数据组织单元
数据页和索引页物理结构相同吗?完全相同,都是16KB,都有File Header/Trailer等
如何区分?通过PAGE_TYPEPAGE_LEVEL等元数据字段
数据页可以变成索引页吗?可以,页分裂、合并时类型可能变化

所以更准确的说法是:数据页和索引页是InnoDB在统一的物理页结构基础上,根据存储内容和在B+树中的位置所做的逻辑区分