PostgreSQL 9.5.10监控查询缓慢,日志报stale stats如何解决?
你遇到的问题核心原因就是系统表统计信息过时——PostgreSQL的查询规划器依赖新鲜的统计数据来生成高效执行计划,当pg_stat_bgwriter这类系统视图的底层统计数据过期时,就会导致监控查询执行效率暴跌,而业务查询不受影响是因为业务表的统计信息可能还保持在有效状态。下面是一步步的解决方案:
1. 手动刷新系统表统计信息(快速见效)
先手动更新相关系统表的统计数据,这是最快让监控查询恢复正常的方法。在psql终端执行以下命令:
-- 针对性刷新核心监控视图对应的系统表统计 ANALYZE pg_catalog.pg_stat_database; ANALYZE pg_catalog.pg_stat_bgwriter; ANALYZE pg_catalog.pg_stat_database_conflicts; -- 或者全面刷新当前数据库所有表(含系统表)的统计 ANALYZE ALL;
执行完成后立刻重试你的监控查询,耗时应该会回到正常水平。
2. 调整Autovacuum配置,防止统计信息再次过期
默认的Autovacuum配置对系统表的自动分析阈值偏保守,当数据库连接、事务频繁变化时,系统表的统计数据更新快,很容易再次过期。
先检查当前Autovacuum参数
确认Autovacuum是否启用,以及核心阈值设置:
SHOW autovacuum; SHOW autovacuum_analyze_threshold; SHOW autovacuum_analyze_scale_factor;
默认的autovacuum_analyze_threshold是50,autovacuum_analyze_scale_factor是0.1(10%)——意味着只有当表中变化行数超过50 + 表行数*10%时才会自动触发ANALYZE,这个阈值对系统表来说太高了。
给核心监控表设置激进的自动分析规则
单独给系统监控相关的表调整参数,让Autovacuum更频繁地更新统计信息:
-- 针对pg_stat_database设置低阈值 ALTER TABLE pg_catalog.pg_stat_database SET ( autovacuum_analyze_threshold = 20, autovacuum_analyze_scale_factor = 0.02 ); -- 给pg_stat_bgwriter做同样配置 ALTER TABLE pg_catalog.pg_stat_bgwriter SET ( autovacuum_analyze_threshold = 20, autovacuum_analyze_scale_factor = 0.02 );
这样只要表中有20 + 2%的行发生变化,Autovacuum就会自动执行ANALYZE,保持统计信息的新鲜度。
3. 验证执行计划(排查潜在问题)
如果手动刷新后查询还是慢,用EXPLAIN ANALYZE查看执行计划,确认是否有其他隐藏问题:
EXPLAIN ANALYZE SELECT * FROM pg_stat_bgwriter;
正常情况下这类系统视图的查询应该毫秒级完成,如果看到全表扫描或异常耗时的操作,可以检查系统表是否膨胀:
-- 查看pg_stat_database的表大小是否异常 SELECT pg_total_relation_size('pg_catalog.pg_stat_database');
如果表大小远超预期,可能需要手动清理系统表(不过PostgreSQL 9.5系统表膨胀概率较低)。
4. 长期建议:升级PostgreSQL版本
PostgreSQL 9.5已经停止官方维护多年(支持截止到2021年1月),新版本在统计信息管理、Autovacuum效率上有大量优化,能从根源减少这类问题。如果条件允许,建议升级到12+的稳定版本。
内容的提问来源于stack exchange,提问作者RootOfProblem

