PostgreSQL:pg_stat_user_tables中seq_scan计数及查询定位问题
1. Bitmap Heap Scan 会不会被统计为 pg_stat_user_tables 中的 seq_scan?
明确说:不会。
pg_stat_user_tables里的seq_scan字段统计的是针对该表的**纯顺序扫描(Sequential Scan)**次数——也就是数据库直接从头到尾扫描整个表数据块的操作。而Bitmap Heap Scan是索引扫描流程的一部分:通常先通过Bitmap Index Scan生成符合条件的行的位图,再根据位图去堆表中抓取对应的行,这个过程属于索引驱动的扫描,不会被计入seq_scan。
你看到seq_scan非零,说明确实有查询在执行全表顺序扫描,不是Bitmap Heap Scan导致的。
2. 如何定位执行顺序扫描的查询?
这里给你几个实用的方法,按推荐程度排序:
方法一:用 pg_stat_statements 追踪历史查询(最推荐)
pg_stat_statements是PostgreSQL的核心扩展,能记录所有执行过的查询的详细统计信息,包括每个查询触发的顺序扫描次数。
首先确保扩展已启用(如果没开,需要先在postgresql.conf里设置shared_preload_libraries = 'pg_stat_statements',然后重启数据库,再执行CREATE EXTENSION pg_stat_statements;)。
然后执行以下查询来找出触发顺序扫描的语句:
SELECT queryid, query, calls, seq_scan, total_time, rows FROM pg_stat_statements WHERE seq_scan > 0 ORDER BY seq_scan DESC;
这个结果会按顺序扫描次数从多到少排序,你可以直接看到哪些查询在频繁触发全表扫。
方法二:用 pg_stat_activity 实时捕获当前运行的顺序扫描
如果想抓正在执行的全表扫,可以查询pg_stat_activity,过滤出当前活跃且正在做Seq Scan的进程:
SELECT pid, datname, usename, query, state FROM pg_stat_activity WHERE state = 'active' AND query LIKE '%Seq Scan on%';
注意这个只能抓到当前正在运行的查询,适合临时排查突发的seq_scan。
方法三:通过数据库日志定位
可以开启PostgreSQL的日志功能来记录相关查询:
- 在
postgresql.conf中设置log_statement = 'all'(会记录所有查询,适合临时排查,不要长期开,避免日志过大),或者log_min_duration_statement = 100(记录执行时间超过100ms的查询,更高效)。 - 然后查看数据库日志文件,搜索关键词
Seq Scan on,就能找到对应的查询语句和执行时间。
方法四:针对可疑表用 EXPLAIN ANALYZE 验证
如果怀疑某个表的seq_scan是特定查询导致的,可以对该查询执行EXPLAIN ANALYZE,看实际执行计划里是否有Seq Scan节点。有时候预估的EXPLAIN计划和实际执行计划不一致(比如表的统计信息过时),这时候EXPLAIN ANALYZE会展示真实的执行路径。
另外,如果你发现预估计划和实际执行计划不符,建议对目标表执行ANALYZE your_table;更新统计信息,让优化器生成更准确的计划。
内容的提问来源于stack exchange,提问作者Xephonia

