七月 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_scanned
与heap_blks_total
在一段时间内的值。如果您看到进度缓慢,并且phase
是scanning 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
中的phase
是vacuuming indexes
,则应检查表上是否有很多索引正在被清理。
如果有许多索引,则可以通过增加 max_parallel_maintenance_workers,并行处理索引来加快 VACUUM 速度。请注意,仅当您手动运行VACUUM
命令时,此配置更改才会有所帮助。(遗憾的是,autovacuum 目前不支持并行清理。)
有了所有这些建议,您应该能够显著地加快清理速度了。