首页/数据/SQL 速查/PG 扫描节点:Seq / Index / Bitmap
性能与执行计划72 条

PG 扫描节点:Seq / Index / Bitmap

Seq Scan、Index Scan、Index Only Scan、Bitmap Heap Scan 各有适用面:识别计划树中的扫描方式判断瓶颈环节。

SQL 速查数据更新于 2026-10-13

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 才能减少回表,只加覆盖索引解决不了这个指标。

易错点

  • 看到 Seq Scan 就断言必须加索引,低选择性查询全表扫描其实更划算
  • 诊断后忘记 RESET enable_* 参数,长期关闭顺序扫描把正常查询也拖慢
  • 只看节点名称不看 rows 与实际耗时,误判真正的瓶颈环节
  • Index Only Scan 出现大量 Heap Fetches 却只怀疑索引设计,忽略表的可见性映射需要维护

数据来源与参考

  • PostgreSQL Documentation §14.1 Using EXPLAIN
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌