PG 扫描节点是什么
EXPLAIN 计划树里的扫描节点说明数据是怎么被读出来的。Seq Scan 顺序全表扫描,小表或需要读取大比例数据时属于正常选择;Index Scan 走索引定位后回表取行,选择性高时成本低;Index Only Scan 只读索引即可返回,但依赖可见性映射,Heap Fetches 偏高说明需要 VACUUM;Bitmap Index Scan 配合 Bitmap Heap Scan 先收集行位置建位图,再按物理顺序取堆,适合中等选择性与多条件组合。识别节点只是第一步,还要结合返回行数与选择率判断是否合理。
基本信息
| 适用平台 | PostgreSQL 11+(EXPLAIN 输出格式一致) |
|---|---|
| 常见节点 | Seq Scan、Index Scan、Index Only Scan、Bitmap Heap Scan、TID Scan |
| 诊断开关 | enable_seqscan / enable_indexscan 等可临时关闭用于对比 |
| Index Only Scan 关键指标 | Heap Fetches:回表次数,偏高说明可见性映射未覆盖 |
| TID Scan | 按 ctid 直接定位行,常见于批量更新后的回写 |
典型使用场景
- 判断一次全表扫描是否合理,而不是看到就加索引
- 排查索引明明存在却没被使用的原因
- 验证覆盖索引是否真的做到免回表
- 定位随机访问过多(回表频繁)的查询
- 用开关做对照实验,确认优化器选择是否受统计信息影响
诊断与验证
诊断与验证
-- 仅用于诊断对比,不要在生产长期关闭顺序扫描
SET enable_seqscan = off;
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE user_id = 100;
RESET enable_seqscan;
-- 观察 Index Only Scan 的回表情形
EXPLAIN (ANALYZE, BUFFERS)
SELECT user_id, created_at FROM orders WHERE user_id = 100;
-- 关注 Heap Fetches:数值偏高说明可见性映射未覆盖,需要及时 VACUUM常见扫描节点
| 节点 | 含义 | 何时算正常 |
|---|---|---|
| Seq Scan | 顺序全表扫描 | 小表,或需要读取表中大比例的行 |
| Index Scan | 索引定位后回表取行 | 选择性高、返回行数少 |
| Index Only Scan | 只读索引即可返回 | 索引已包含查询所需全部列 |
| Bitmap Index Scan + Bitmap Heap Scan | 先建位图再按物理序取堆 | 中等选择性、多条件组合 |
| TID Scan | 按 ctid 定位行 | 批量更新后的回写阶段 |
位图扫描会先把符合条件的行位置收集成位图,再按物理顺序读取,代价是位图构建的内存与时间开销;返回行数占比过高时优化器会自动退回顺序扫描,这不是异常。
Index Only Scan 的 Heap Fetches 偏高说明可见性映射没有覆盖到这些页面:及时 VACUUM 才能减少回表,只加覆盖索引解决不了这个指标。