PostgreSQL v12 vacuum内存限制未强制执行问题咨询
PostgreSQL VACUUM ANALYZE内存超限原因说明
核心结论:maintenance_work_mem仅限制VACUUM清理环节的内存占用,不覆盖ANALYZE统计信息生成阶段的内存开销,这是你观测到进程内存远超配置阈值的根本原因。
具体原因拆解
- VACUUM和ANALYZE的内存管控规则完全独立
- 单纯VACUUM清理死元组的环节,内存确实受
maintenance_work_mem(手动执行)或autovacuum_work_mem(自动触发)限制,这部分内存用来存储待清理的死元组指针,不会超过配置阈值。 - ANALYZE生成统计信息的环节,内存占用不受
maintenance_work_mem管控,它的开销直接和default_statistics_target配置、目标表的字段数量正相关。
- 单纯VACUUM清理死元组的环节,内存确实受
- 高
default_statistics_target带来的额外内存开销
你将default_statistics_target从100调整到3000,意味着PostgreSQL需要为每个字段采集30倍的采样数据,生成更细粒度的高频值列表、直方图等统计信息。如果你的mdm_context表字段较多,ANALYZE阶段申请几百MB的私有临时内存属于正常现象,这部分内存不在maintenance_work_mem的限制范围内。 - 实测数据验证
从你提供的进程监控数据可以直接印证上述逻辑:- 第一次执行
VACUUM ANALYZE时default_statistics_target=100,进程RES为165996KB≈162MB,其中SHR占139068KB≈136MB,这部分就是shared_buffers的映射,私有内存仅26MB左右,扣除进程基础开销后完全符合20MB的maintenance_work_mem限制。 - 第二次调整
default_statistics_target=3000后执行,进程SHR仅2976KB≈3MB,说明绝大部分RES都是ANALYZE阶段申请的私有临时内存,这部分既不占用maintenance_work_mem配额,也不占用shared_buffers配额,自然会超过20MB+128MB的总和。
- 第一次执行
优化建议
- 如果不需要全局高精度统计信息,可适当调低全局
default_statistics_target,仅对有特殊需要的表单独设置表级statistics_target即可。 - 如果确实需要高精度统计信息,可接受这部分临时内存开销,ANALYZE执行完成后内存会自动释放。
内容的提问来源于stack exchange,提问作者nmakb
相关产品推荐
相关产品推荐

