页面布局的设计挑战
数据页设计面临两个核心矛盾:
- 变长字段:字符串、JSON、数组长度不固定
- 原地更新 vs 追加写入:如何平衡写性能与读性能
Slotted Pages
Slotted Pages 是关系数据库最主流的页面布局,PostgreSQL 和 MySQL InnoDB 均采用此设计。
┌──────────────────────────────────────┐
│ Page Header │
│ ┌──────────┬──────────────┐ │
│ │ LSN (8B) │ Free Space Ptr│ ... │
│ └──────────┴──────────────┘ │
├──────────────────────────────────────┤
│ │
│ Free Space (Gap) │
│ ↓ ↓ ↓ ↓ ↓ ↓ ↓ │
│ │
├──────────────────────────────────────┤
│ Tuple 2 (id=2, name="Bob") │
├──────────────────────────────────────┤
│ Tuple 1 (id=1, name="Alice") │
├──────────────────────────────────────┤
│ Item Pointers │
│ ┌─────────────────────────────────┐ │
│ │ Slot 1: offset=XXX, length=YYY │ │
│ │ Slot 2: offset=XXX, length=YYY │ │
│ └─────────────────────────────────┘ │
└──────────────────────────────────────┘
核心特性
- Tuple 从页尾向前增长,Slot 数组从页头向后增长
- Slot 数组记录每条 Tuple 的偏移和长度,支持变长字段
- 删除只需标记 Slot,无需移动数据(通过 vacuum 回收空间)
- Heap-Only Tuple (HOT) 更新:在同页内创建新版本,不更新索引
PostgreSQL 的具体实现
// src/include/storage/bufpage.h
typedef struct PageHeaderData {
PageXLogRecPtr pd_lsn; // WAL LSN
uint16 pd_checksum; // 校验和
uint16 pd_flags; // 标志位
LocationIndex pd_lower; // 空闲空间的起始偏移
LocationIndex pd_upper; // 空闲空间的结束偏移
LocationIndex pd_special; // 特殊空间偏移
uint16 pd_pagesize_version;
ShortTransactionId pd_prune_xid;
ItemIdData pd_linp[FLEXIBLE_ARRAY_MEMBER]; // 行指针数组
} PageHeaderData;
其他布局方案
日志结构页面
不覆盖旧数据,追加写入新版本:
Page v1: [Tuple A, Tuple B]
Page v2: [Tuple A, Tuple B', Tuple C] ← 追加 B' 和 C
Page v3: [Tuple A, Tuple B', Tuple C']
- 优势:写入极快(顺序追加),崩溃恢复简单
- 劣势:需要 compaction 合并版本,读放大
- 代表:LSM-Tree(RocksDB)、WiredTiger
PAX(Partition Attributes Across)
页面内按列分组:
┌─────┬──────────┬──────────┬──────────┐
│ │ Column A │ Column B │ Column C │
│Row 1│ val_a1 │ val_b1 │ val_c1 │
│Row 2│ val_a2 │ val_b2 │ val_c2 │
│ ... │ ... │ ... │ ... │
└─────┴──────────┴──────────┴──────────┘
- 优势:列式计算高效,压缩比高
- 劣势:行级操作需要多次内存跳转
- 代表:DuckDB、MonetDB/X100
总结
| 方案 | 适用场景 | 代表系统 |
|---|---|---|
| Slotted Pages | OLTP(读写均衡) | PostgreSQL, MySQL |
| 日志结构 | 写密集 | RocksDB, Cassandra |
| PAX/列存 | 分析查询 | DuckDB, Vertica |