Buffer Pool + 页结构(理解为什么随机查会慢)
🚀 一句话先打基础
InnoDB 的最小读写单位是“页(Page)”,默认大小 16KB。
Buffer Pool 就是这些“页”的内存缓存池。
查一次数据,就是从磁盘把一个 16KB 的页搬到内存。
📦 1. 什么是页(Page)?
想象你有一本书,每一页 16KB。
你查一本书的某一段内容,肯定不会“翻到单独一个字”,而是整页整页地看。
MySQL 也是这么干的:
- 数据是按照 页 存储的
- 查询必须把 整页 读到内存
- 页里包含多行记录(几十~几百行,和你的行宽有关)
👉 所以 “查一行数据” = 读一个 16KB 页。
不管你只要其中的一条还是全部,它都是整页。
🧊 2. 什么是 Buffer Pool?
Buffer Pool = 页的高速缓存池。
你把它想成一个堆满“热数据页”的仓库:
- 查询命中 Buffer Pool → 秒回
- 查询没命中 → 需要从磁盘读页 → 多一次磁盘 I/O
而磁盘 I/O 就是数据库性能最大杀手。
读取一个页(随机 I/O):
- SSD:0.1ms ~ 0.5ms
- 内存:几十纳秒
差了 约 2 万倍。
所以 Buffer Pool 命中率 对性能影响极大。
🧱 3. 页结构长啥样?
一个页(16KB)里大致包含:
+--------------------------------+
| Page Header (头部信息) |
+--------------------------------+
| Infimum/Supremum (虚拟行) |
+--------------------------------+
| User Records (真正的数据)|
+--------------------------------+
| Free Space (空闲空间) |
+--------------------------------+
| Page Directory (槽) |
+--------------------------------+
| Trailer (校验) |
+--------------------------------+
核心是:
💥 页里不是乱存的
数据按主键排序,用链表串起来(物理有序不存在,只是页内有序)。
💥 页目录(slots)让查找更快
类似“页内索引”,让查某行不需要线性扫描。
这也解释了:
- 为什么主键自增插入快
- 为什么随机主键插入会分裂页、很慢
🧭 4. 为什么随机查询会慢?(核心来了)
我们以 主键查询 id=1 vs 随机条件查询 name='Tom' 对比:
场景 A:主键查询(顺序 I/O)
主键索引(聚簇索引)是一棵 B+Tree。
查 id=100:
- B+Tree 找到对应叶子节点页
- 叶子节点里的那个“页”读出来
- 返回结果
只需要查一次叶子节点 + 根节点缓存通常在 Buffer Pool
→ I/O 次数极少
主键查找性能非常稳定。
场景 B:随机条件(非主键)查询(随机 I/O)
比如:
SELECT * FROM user WHERE name = 'Tom';
流程变成:
- 先查 name 的二级索引(非聚簇索引)
- 找到记录对应的主键值(例如 id = 100)
- 再去聚簇索引树里根据主键“回表”查数据
- 这意味着至少两个页要被读入内存
如果这两个页都不在 Buffer Pool?
→ 两次磁盘随机 I/O
再想象有成千上万条,需要回表成千上万次……
随机查询为什么慢:
因为会导致大量“回表”,而每次回表都是一次随机 I/O。
百万级表随机查询 → I/O 炸裂。
💣 进一步:为什么范围查询快?
因为 InnoDB 页之间通过双向链表连接。
查主键范围:
WHERE id BETWEEN 1 AND 100000
只需要:
- 找到第一页
- 顺着链表向后遍历页数据
(顺序 I/O,磁盘一次读多个连续页 → 快)
而随机条件查 name='Tom'
→ 分布到不同页 → 全是随机 I/O → 颠簸死
🎯 随机查询慢的终极原因总结
✔ 页是 16KB
✔ 查询必须整页加载
✔ 随机数据可能分散在大量页里
✔ 每次回表都是一次磁盘随机 I/O
✔ Buffer Pool 容量有限,不可能所有页都常驻内存
✔ 随机 I/O 是数据库最贵的操作,慢几十倍到几万倍
所以:
随机查询 = 大量随机读页 = 性能自杀。
🔧 工程师能用的优化方法(你马上能用)
- 尽量让查询变成主键查询
- 尽量用覆盖索引(避免回表)
- 让热点数据留在 Buffer Pool
- 页分裂要尽量少(使用自增主键)
- 表越“大页”,Buffer Pool 越“紧张”
- 删掉无用索引,避免写放大
浙公网安备 33010602011771号