Postgres执行ANALYZE未扫描全量页面的影响及解决方法
问题解答
未扫描完全部页面是否会引发运行问题
你观测到的命令输出:
scanned 30000 of 609920 pages, containing 560268 live rows and 35063 dead rows; 30000 rows in sample, 11390622 estimated total rows
这不是ANALYZE命令执行中断或者运行异常,是PostgreSQL默认配置下的正常行为:默认default_statistics_target参数值为100时,ANALYZE对单表最多采样30000个页面就会完成统计计算,该机制的设计目标就是通过科学采样生成足够支撑查询规划的统计信息,本身就不需要扫描全表所有页面。
常规业务场景下,这种默认采样的精度完全足够,不会引发数据库运行故障、数据错误这类严重问题,仅在少数特殊场景下可能产生负面影响:
- 当大表的数据分布极度倾斜(比如某几个过滤值占全表数据量30%以上、但采样页面刚好没覆盖到这些值对应的存储区间)时,查询规划器可能拿到偏差较大的统计结果,选错执行计划,比如错误选择全表扫描代替索引扫描、多表关联时选错驱动表,引发偶发慢查询。
- 跨大版本升级后如果统计信息格式有迭代,默认采样如果未覆盖核心业务的查询过滤范围,可能在升级后初期出现短暂的性能抖动,但不会触发数据库宕机、数据损坏类的致命问题。
完成全页面扫描分析的操作方法
PostgreSQL原生ANALYZE没有直接提供“强制扫描全页”的开关,你可以通过调高统计目标的方式实现全页面扫描,操作如下:
- 核心逻辑:将统计目标阈值调整到PostgreSQL支持的最大值10000,该参数下ANALYZE会覆盖扫描全表所有页面,生成精度最高的统计信息,你可以根据需求选择以下任意一种操作方式:
- 临时对单个大表做全量分析(推荐升级校准场景使用),执行以下SQL即可:
-- 仅调整当前会话的默认统计目标到最大值,不影响全局配置 SET default_statistics_target = 10000; -- 对目标表执行全量分析 ANALYZE VERBOSE 你的目标表名; - 若需要长期让该表保持最高精度的统计信息,可以直接修改表字段的持久化统计目标配置:
-- 对需要高统计精度的字段单独设置统计目标,不需要对所有字段操作 ALTER TABLE 你的目标表名 ALTER COLUMN 参与查询过滤/关联的字段名 SET STATISTICS 10000; -- 配置生效后重新执行分析 ANALYZE VERBOSE 你的目标表名;
- 临时对单个大表做全量分析(推荐升级校准场景使用),执行以下SQL即可:
- 操作注意事项:
- 全页面扫描的ANALYZE会产生大量顺序IO,不要在业务高峰期执行,建议选择业务低峰窗口操作,避免IO打满影响正常业务读写。
- 若只是升级后临时需要全量统计校准,全量分析完成后可以把统计目标改回默认值100,避免过高的统计目标增加查询规划阶段的计算开销。
内容的提问来源于stack exchange,提问作者Kumar
相关产品推荐
相关产品推荐

