函数中的 Postgres 真空

Bru*_*ngo 4 postgresql performance vacuum postgresql-performance

谷歌搜索后,很明显你不能从函数运行真空:

Postgres 邮件 - plpgsql 函数中的真空行为

由于内存管理限制,您无法从函数内部运行 VACUUM。在当前来源中有一个错误检查以防止您尝试。

Stackoverflow - 无法从函数或多命令字符串执行 VACUUM

加载数据后,我想对受影响的表进行“真空分析”,既要从已删除的记录中恢复空间,又要准确反映新内容。[...] 当我运行这个时,我得到:

ERROR: VACUUM cannot be executed from a function or multi-command string

但是我真的需要在运行某个函数时“自动”运行vacuum:这个函数更新了很多记录(如果不是全部),所以死行的数量增加得非常快,其他查询性能下降很多。问题是该函数是从另一个程序调用的。任何最佳实践?我应该在函数执行后手动将真空语句添加到一段单独的代码中,就像

sql = SELECT my_function() <program.execute(sql)> sql = VACUUM [FULL | ANALYZE] my_updated_table <program.execute(sql)>

Ava*_*rkx 5

文档页面:

提示:当由于大量更新或删除活动而导致表包含大量死行版本时,纯 VACUUM 可能无法令人满意。如果您有这样的表并且需要回收它占用的多余磁盘空间,则需要使用 VACUUM FULL,或者 CLUSTER或 ALTER TABLE 的表重写变体之一。这些命令重写表的整个新副本并为其构建新索引。所有这些选项都需要排他锁。请注意,它们还会临时使用大约等于表大小的额外磁盘空间,因为表和索引的旧副本在新副本完成之前无法释放。

如果您无法摆脱对表的排他锁,那么您也可以使用 simple ANALYZE <tablename>;,因为这只会占用一个读锁并且应该更新表的统计信息并减少(如果不能完全消除)性能下降对于其他查询。然后,您可以让常规的 autovacuum 守护程序正常执行它的操作(或任何您当前的自定义真空解决方案)。

如果你的表甚至没有聚集索引,你首先需要做一个ALTER TABLE <tablename> CLUSTER ON <indexname>;. 无论如何,您可能应该拥有某种聚集索引:拥有庞大的堆表和针对它的糟糕性能通常是齐头并进的。

就最佳实践而言,我非常倾向于推荐这种ANALYZE方法,因为执行自动统计更新远远优于自动索引重建或几乎任何形式的VACUUM FULL运行,而无需管理员积极监视。