
首先需要说明的是关闭autovacuum 这个想法并不是 DB 的想法,而是开发的想法,想法的来源与,AUTOVACUUM 在工作时时间很长,他们认为影响了数据库的正常运行,如果针对PG 的数据库本身不能正常的维护,突然对一些大表进行 AUTOVACUUM 的确是对CPU有明显的性能消耗。

首先AUTOVACUUM 能不能关闭 和 应不应该被关闭是两个话题,以下的内容是基于能不能关闭,而不是应该不应该关闭。
AUTOVACUUM 能不能被关闭,可以。但AUTOVACUUM 被关闭也分为及多种方式
1 整体关闭的关闭也分为不同的方式
1.1 野蛮关闭 , 直接在autovacuum 将其设置为 off 将

这样的方式将AUTOVACUUM 进行关闭,是我们不提倡的,关闭后数据库会遇到众多的问题。但这是一种关闭的方式。
1.2 autovacuum_vacuum_cost_limit 调整更低,这个值是在200到10000进行调整的,值越大那么可以接受的所有的autovacuum的 进程合并的成本就越大,autovacuum 就会约积极,而将这个值变小在autovacuum中就会发生只要操作就初级成本的底线,autovacuum就会暂停,如果在配置

autovacuum_vacuum_cost_delay = 100 ms 这样虽然不能杜绝autovacuum 开始工作,但可以让autovacuum 马上触发限制并停止工作,同时如果此时多开一些 autovacuum_max_workers = 更多的进程,则autovacuum 基本上就无法进行工作了。
通过下面的SQL 可以监控autovacuum 的工作是否在进行。
SELECT p.pid,
p.datname,
p.query,
p.backend_type,
a.phase,
a.heap_blks_scanned / a.heap_blks_total::float * 100 AS "% scanned",
a.heap_blks_vacuumed / a.heap_blks_total::float * 100 AS "% vacuumed",
pg_size_pretty(pg_table_size(a.relid)) AS "table size",
pg_size_pretty(pg_indexes_size(a.relid)) AS "indexes size",
pg_get_userbyid(c.relowner) AS owner
FROM pg_stat_activity p
JOIN pg_stat_progress_vacuum a ON a.pid = p.pid
JOIN pg_class c ON c.oid = a.relid
WHERE p.query LIKE 'autovacuum%';
1.3 除此以外我们还有一个关闭AUTOVACUUM 的方式
这两个参数是老面孔了,在每个表到什么情况下触发进行autovacuum的操作
autovacuum_vacuum_threshold
autovacuum_vacuum_scale_factor

公式为
表的行数* autovacuum_vacuum_scale_factor + autovacuum_vacuum_threshold
如果我按照图上的设置来进行,估计一般的PG 数据库是不会在进行 autovacuum的操作了,因为都不符合条件。
2 这对表进行关闭
上面的操作估计是比较狠,所以实际上用的可能性不多,但是下面的方式就比较可能是常用的,针对表的操作,也就是某些不讨喜的大表,我们希望我们自己手动vacuum进行操作,而不是让他自动运行,避免白天对某些表长时间的进行autovacuum ,有些没有维护好的表,一次autovacuum 做 1 到2个小时是经常的事情。
第一种方式是直接关闭
此时值需要进入到数据库中,针对要关闭autovacuum 的表操作如下的命令就可以将表的autovacuum操作关闭。
ALTER TABLE table_name SET (autovacuum_enabled = off/on);
第二种方式是从上面的1.3 进行照抄,但针对的是对表的操作
ALTER TABLE public.iddd SET (autovacuum_vacuum_scale_factor = 0.9,autovacuum_vacuum_threshold = 1000000000);

通过尝试也知道 autovacuum_vacuum_threshold 的参数是不能设置成100亿,20亿是可以的。估计这个和 txid 有关,这里就不细究了。
说完这些,从PG13开始添加了两个参数
autovacuum_vacuum_insert_threshold
autovacuum_vacuum_insert_scale_factor
如果此时你使用的是PG 13 及以上的版本,如果你希望关闭autovacuum的操作还需要对这两个参数进行修改,方式和上面的类似。
那么说了半天,到底为什么要关闭AUTOVACUUM ,实际上还是和autovacuum 在操作中对系统的性能损耗有关。尤其针对超大表,如果一个表有几百G ,我想扫描一次的成本并不低,尤其针对超大表并且没有进行优化调整autovacuum触发的参数的的表,长期针对大表不进行autovacuum ,而后期触发后,发生的autovacuum的成本是比较高的,同时一个表如果有多个索引,这个问题将发生的更加明显,根据日常工作中的经验,如果一个表的索引超过6个以上,则整体的 autovacuum 的工作时间70 -80%的时间都在索引本身,而不再表本身,所以
1 发现经常对表进行autovacuum,但是就是做不完,或者时间很长的情况下,并且影响到系统的性能的情况下
1 通过上面将表的 autovacuum 暂时关闭,避免影响业务
2 在非业务时间,运行 vacuum 针对这个表,并且如果发现还做不完的情况下,可以查看索引的碎片情况,如果碎片严重,那么加以删除索引,然后在做 vacuum , 在重建索引。
3 在这些都完成后,优化这个表在 autovacuum触发的频次,不要等待长期不进行autovacuum ,等到触发的时候,已经追悔莫及。
4 注意大表被autovacuum轮训的情况,如果大表比较多,很可能会导致某些表无法被即使轮休到,所以调整 autovacuum works 也需要考虑
最后总结, POSTGRESQL 原理使然,UNDO 在每个表中,那么管理和维护也需要更加的细节化,注定PG 在应用设计上, 管理维护上,都需要一个懂得他的 “好保姆”。

PostgreSQL autovacuum 管理与优化策略
本文探讨了 PostgreSQL 数据库中 autovacuum 的工作原理和影响,以及在性能考虑下关闭或调整 autovacuum 的不同方法。关闭 autovacuum 可能会导致数据库问题,但可以通过调整参数限制其活动。对于大表,长时间的 autovacuum 可能影响性能,建议在非业务时间手动运行 vacuum,并优化触发条件。关键词包括 PostgreSQL、autovacuum、性能优化、数据库维护。
1546

被折叠的 条评论
为什么被折叠?



