我们在Amazon RDS中有一个postgres数据库。最初,我们需要快速加载大量数据,因此根据autovacuum
关闭了best practice suggestion from Amazon。最近我在运行查询时发现了一些性能问题。然后我意识到它已经很长时间没有被吸尘了。事实证明,许多表都有很多死元组。
令人惊讶的是,即使我在某些表上手动运行vacuum
命令,它似乎也没有删除这些死元组。 vacuum full
需要很长时间才能完成,这通常会在一整夜之后结束。
为什么vacuum
命令不起作用?我的其他选择是什么,重启实例?
使用VACUUM (VERBOSE)
获取有关它正在做什么以及为什么做的详细统计数据。
无法删除死元组有三个原因:
SELECT pid, datname, usename, state, backend_xmin
FROM pg_stat_activity
WHERE backend_xmin IS NOT NULL
ORDER BY age(backend_xmin) DESC;
你可以用pg_cacnel_backend()
or pg_terminate_backend()
摆脱交易。SELECT gid, prepared, owner, database, transaction
FROM pg_prepared_xacts
ORDER BY age(transaction) DESC;
用户COMMIT PREPARED
或ROLLBACK PREPARED
关闭它们。SELECT slot_name, slot_type, database, xmin
FROM pg_replication_slots
ORDER BY age(xmin) DESC;
使用pg_drop_replication_slot()
删除未使用的复制槽。https://dba.stackexchange.com/a/77587/30035解释了为什么不删除所有死元组。
为vacuum full
不要超时,设置statement_timeout = 0
http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_BestPractices.html#CHAP_BestPractices.PostgreSQL建议在数据库恢复时禁用autovacuum,进一步他们建议使用它:
重要
不运行autovacuum可能导致最终需要中断以执行更具侵入性的真空操作。
取消所有会话和清理表应该有助于以前的死元组(关于重新启动集群的建议)。但我建议你先做的事情 - 切换autovacuum。更好的可能控制真空在桌子上,而不是整个集群与autovacuum_vacuum_threshold
,(ALTER TABLE
)参考这里:https://www.postgresql.org/docs/current/static/sql-createtable.html#SQL-CREATETABLE-STORAGE-PARAMETERS