PostgreSQL 教程: 提升 VACUUM 处理速度

七月 17, 2024

摘要:在本教程中,您将学习如何在 PostgreSQL 中提升 VACUUM 的处理速度。

目录

您可能会遇到的与 autovacuum 相关的问题是,您的表清理速度太慢。这可能表现为膨胀量的增长,因为您清理膨胀的速度慢于事务量的速度。或者,当您查看pg_stat_activity时,您会看到系统上一直在运行的 VACUUM 进程。

有几种方法可以加快 VACUUM 速度:这些建议既适用于 autovacuum,也适用于手动触发的VACUUM

减少开销限制的影响

您应该检查的第一件事是,是否启用了开销限制。当 VACUUM 在运行时,系统会维护一个计数器,用于跟踪不同 I/O 操作的估计开销。当开销超过autovacuum_vacuum_cost_limit(或vacuum_cost_limit) 时,进程将休眠autovacuum_vacuum_cost_delay(或vacuum_cost_delay)毫秒。这称为开销限制,旨在减少 VACUUM 对其他进程的影响。

如果您发现 VACUUM 滞后,您可以禁用开销限制(通过设置autovacuum_vacuum_cost_delay为 0),或者通过降低autovacuum_vacuum_cost_delay或调高autovacuum_vacuum_cost_limit(如 10000)来减少其影响。

增加并行工作进程的数量

Autovacuum 只能并行清理autovacuum_max_workers个表。因此,如果您有数百个表正在被频繁写入(并且需要被清理),那么一次清理 3 个表可能需要一段时间(3 是autovacuum_max_workers的默认值)。

因此,在具有大量活动表的场景中,可能需要将 autovacuum_max_workers 增加到更高的值(假设您有足够的计算能力,来支持运行更多的 autovacuum 工作进程)。

在增加 autovacuum 工作进程的数量之前,请确保您不受开销限制的限制。开销限制由所有活跃的 autovacuum 工作进程共同承担,因此仅仅增加并行工作进程的数量,可能无济于事,因为每个工作进程都会开始做更少的工作。

要找到有关如何优化的更多想法,可以尝试观察 pg_stat_progress_vacuum,以了解您正在进行的 VACUUM 处于哪个阶段,以及如何提高其性能。让我们看几个例子,它可能会提供一些有用的见解。

通过预读和缓存提高扫描速度

要了解 VACUUM 的进展速度有多快,您可以比较pg_stat_progress_vacuum中的heap_blks_scannedheap_blks_total在一段时间内的值。如果您看到进度缓慢,并且phasescanning heap,则意味着 VACUUM 需要扫描大量堆块才能完成。

在这种情况下,您可以通过使用 pg_prewarm 之类的工具,将较大的关系表预读到内存中,或增加shared_buffers来更快地扫描堆表。

增加内存以存储更多死元组

扫描堆时,VACUUM 会收集内存中的死元组。它可以存储的死元组数由maintenance_work_mem决定(或者由autovacuum_work_mem决定,如果设置了的话)。收集到最多的元组数后,VACUUM 必须切换到清理索引,然后在索引和堆被清理后(即在进行一次索引清理循环之后),再次返回扫描堆。

所以,如果你注意到pg_stat_progress_vacuum中的index_vacuum_count很高,那就意味着 VACUUM 必须执行许多次这样的索引清理循环。

为了减少 VACUUM 所需的循环次数并使其更快,您可以增加autovacuum_work_mem值,以便 VACUUM 在每次循环可以存储更多的死元组。

并行清理索引

如果您看到在很长时间内,pg_stat_progress_vacuum中的phasevacuuming indexes,则应检查表上是否有很多索引正在被清理。

如果有许多索引,则可以通过增加 max_parallel_maintenance_workers,并行处理索引来加快 VACUUM 速度。请注意,仅当您手动运行VACUUM命令时,此配置更改才会有所帮助。(遗憾的是,autovacuum 目前不支持并行清理。)

有了所有这些建议,您应该能够显著地加快清理速度了。

了解更多

PostgreSQL 优化