PostgreSQL 11.8 基于UNION ALL视图的EXPLAIN生成计划耗时过长问题咨询
问题成因
该问题本质是PostgreSQL 11版本的分区表规划器性能缺陷,所有耗时都集中在执行计划生成阶段(你提供的执行计划中Planning Time高达1844806ms,即约30分钟,也验证了这一点),具体原因如下:
- PostgreSQL 11的分区裁剪逻辑效率极低,当查询涉及UNION ALL拼接的普通表+分区父表时,规划器需要遍历分区父表下的所有子分区,逐个读取每个分区的元数据、校验分区约束是否匹配查询过滤条件,才能完成不匹配分区的裁剪。分区数量越多、系统表元数据越膨胀,该过程耗时越长。
- 单独查询普通热表或分区父表时,规划器不需要处理UNION ALL分支的路径合并逻辑,约束检查的计算量更低,所以可以快速返回执行计划。
- 无锁等待、状态为active的特征也符合规划阶段CPU密集计算的表现,不存在执行层的资源阻塞。
解决方法
根本解决
- 升级PostgreSQL到12及以上版本,12及之后的版本对分区表规划逻辑做了大量深度优化,同等场景下分区裁剪的耗时可以降到11版本的1%以下,是最高效的解决方案。
兼容版本优化
- 检查参数配置:确保
constraint_exclusion参数值为partition(默认值)、enable_partition_pruning参数为on,避免分区裁剪逻辑被关闭。 - 优化系统表状态:执行
VACUUM ANALYZE pg_class;、VACUUM ANALYZE pg_constraint;清理系统表的死元组,降低元数据读取的开销;如果系统表膨胀严重,可以在业务低峰期执行VACUUM FULL pg_class;等命令回收空间(该操作会锁表,需谨慎操作)。 - 优化视图与查询逻辑:如果查询固定带时间范围过滤条件,可以修改视图定义,将时间过滤条件直接下推到UNION ALL的两个分支中,减少规划器的计算量;也可以定期将不在业务查询范围内的冷分区从父表中detach,降低规划阶段需要遍历的分区数量。
- 更新统计信息:全量分析分区父表的统计信息,执行
ANALYZE myappli_histo.traffic_partitionned_parent_table;,避免规划器因为统计信息缺失做额外的计算。
临时应急方案
- 如果查询条件固定,可以使用预备语句(PREPARE)缓存执行计划,后续执行时不需要重复生成计划,跳过漫长的规划阶段。
内容的提问来源于stack exchange,提问作者Enialis
相关产品推荐
相关产品推荐

