执行VACUUM FULL后n_dead_tup及表大小未改变的原因咨询
统计信息未实时刷新
pg_stat_all_tables中的n_dead_tup等统计字段并非实时更新,而是依赖PostgreSQL的自动统计收集器定期同步(默认更新间隔约5分钟)。即使VACUUM FULL已完成死元组清理,统计视图可能仍显示旧数据。你可以手动执行ANALYZE <目标表名>强制更新该表的统计信息,之后再查询pg_stat_all_tables即可看到最新数值。分区表未清理子分区
如果目标表是分区表,直接对主表执行VACUUM FULL仅会处理主表本身(主表通常无实际数据),所有业务数据都存储在各个子分区中。这种情况下需要逐个对每个子分区执行VACUUM FULL <子分区表名>,才能真正清理死元组并回收存储空间。完成后再查询主表的统计信息,n_dead_tup和表大小才会对应下降。存在未释放的事务或锁
即使你停止了显式操作,数据库中可能仍存在未提交的隐性事务、空闲事务或持有表锁的连接,导致VACUUM FULL无法彻底回收空间。可以通过以下语句排查:- 查看表相关锁:
SELECT * FROM pg_locks WHERE relation = '<目标表名>'::regclass; - 查看关联连接:
SELECT * FROM pg_stat_activity WHERE query LIKE '%<目标表名>%';
终止异常连接后,重新执行VACUUM FULL即可生效。
- 查看表相关锁:
误操作了同名表
如果数据库内存在不同schema下的同名表,可能你执行VACUUM FULL的对象与查询pg_stat_all_tables的表并非同一实体。建议查询时指定schema确认:SELECT n_live_tup, n_dead_tup, relname, schemaname FROM pg_stat_all_tables WHERE relname = '<目标表名>';
确认后对正确schema下的表执行VACUUM FULL即可。
内容的提问来源于stack exchange,提问作者takotsubo

