Postgres:“真空”命令不能清理死元组

ddd*_*ddd 5 postgresql vacuum

我们在Amazon RDS中有一个postgres数据库。最初,我们需要快速加载大量数据,因此autovacuum根据Amazon最佳实践建议将其关闭。最近,我在运行查询时注意到一些性能问题。然后我意识到它已经很长时间没有被清理干净了。事实证明,许多表都有很多死元组。

在此处输入图片说明

令人惊讶的是,即使我vacuum在某些表上手动运行了命令,它似乎也根本没有删除这些无效的元组。vacuum full需要太长时间才能完成,通常一整夜后超时。

为什么vacuum命令不起作用?我还有其他选择,重新启动实例吗?

Lau*_*lbe 7

使用VACUUM (VERBOSE)来获得它在做什么以及为什么详细统计。

无法删除死元组的原因有三个:

  1. 有一个长期运行的事务尚未关闭。你可以找到坏男孩

    SELECT pid, datname, usename, state, backend_xmin
    FROM pg_stat_activity
    WHERE backend_xmin IS NOT NULL
    ORDER BY age(backend_xmin) DESC;
    
    Run Code Online (Sandbox Code Playgroud)

    您可以使用pg_cancel_backend()pg_terminate_backend()摆脱交易。

  2. 有尚未提交的准备好的事务。你可以找到他们

    SELECT gid, prepared, owner, database, transaction
    FROM pg_prepared_xacts
    ORDER BY age(transaction) DESC;
    
    Run Code Online (Sandbox Code Playgroud)

    用户COMMIT PREPAREDROLLBACK PREPARED关闭它们。

  3. 有一些未使用的复制插槽。用找到

    SELECT slot_name, slot_type, database, xmin
    FROM pg_replication_slots
    ORDER BY age(xmin) DESC;
    
    Run Code Online (Sandbox Code Playgroud)

    使用pg_drop_replication_slot()删除未使用的复制插槽。