0

我们注意到我们的一个表在 PG 12 上显着增长。这个表是非常频繁更新的目标,混合了列类型,包括一个非常大的text列(通常包含超过 50kb 的数据)——我们运行一个本地 cron查找早于 X 时间的行并将text列设置为空值的作业(因为在 X 时间后我们不再需要该特定列的数据)。

我们知道,由于 MVCC 模型,这实际上并没有释放磁盘空间,但我们希望 auto-vacuum 能够解决这个问题。令我们惊讶的是,在没有自动真空运行的情况下,该表继续增长(现在超过 40GB)。手动运行真空已经解决了这个问题,我们不再看到增长。

这导致我调查其他表,我意识到我根本不了解自动真空是如何触发的。

这是我对其工作原理的理解,希望有人可以将其分开:

  • 我寻找其中有大量死元组的表: select * from pg_stat_all_tables ORDER BY n_dead_tup desc;
  • 我认同tableX33169557 个死元组(n_dead_tup 列)。
  • 我运行 aselect * from pg_class ORDER BY reltuples desc;来检查表上有多少估计行tableX
  • 我通过列识别了 1725253 行reltuples
  • 我确认我的 autovacuum 设置:autovacuum_vacuum_threshold = 50autovacuum_vacuum_scale_factor = 0.2
  • 我应用公式threshold + pg_class.reltuples * scale_factor,所以,50 + 1725253 * 0.2它返回 345100.6

据我了解,一旦找到 ~345100 个死元组,自动真空将在此表上启动。但是tableX已经达到了惊人的 33169557 个死元组!, 这个表上的 last_autovacuum 是在 2 月份。

欢迎任何澄清。

4

1 回答 1

1

你的算法是绝对正确的。

以下是一些可能出错的原因:

  • autovacuum 运行,但速度太慢以至于它永远不会完成

    如果您没有看到正在运行的 autovacuum,那不是您的问题。

  • autovacuum 运行,但长时间运行的打开事务阻止它删除死元组

  • 其他表需要更紧急地清空(避免事务 ID 环绕),所以三个工作人员忙于其他事情

  • autovacuum 运行,但与表上的高并发锁冲突 ( LOCK TABLE, ALTER TABLE, ...)

    这使得 autovacuum 放弃并稍后再试。

  • autovacuum 已禁用,可能仅适用于该表

于 2021-05-10T13:26:04.840 回答