自动清理和分析表格
Autovacuum 是一个进程守护程序(也就是说,它在后台运行),它会自动 vacuum(清理)死元组,回收存储空间并收集统计信息。它会检查数据库中是否有膨胀的表,并清除膨胀以重新利用这些空间。它会监控数据库表和索引,并在这些表或索引的更新或删除操作达到特定阈值后,将它们添加到 vacuum 作业中。
Autovacuum 通过自动执行 PostgreSQL VACUUM 和 ANALYZE 命令来管理 vacuum 操作。VACUUM 从表中移除膨胀并回收空间,同时 ANALYZE 更新统计信息,使优化程序能够制定有效的计划。VACUUM 还执行一项名为 vacuum 冻结的主要任务,以防止数据库中出现事务 ID 循环问题。数据库中每一个被更新的行都会从 PostgreSQL 事务控制机制中获得一个事务 ID。这些 ID 控制着行在其他并发事务中的可见性。事务 ID 是一个 32 位的数字。二十亿个 ID 永远保留在可见的过去。其余(约 22 亿)ID 保留用于将来将要发生的事务,并且隐藏在当前事务之外。PostgreSQL 需要偶尔清理和冻结旧行,以防止事务回绕并在创建新事务时使旧的现有行不可见。有关更多信息,请参阅 PostgreSQL 文档中的防止事务 ID 重现故障
建议使用 Autovacuum 且它在默认情况下处于启用状态。其参数包括以下选项:
参数 。 |
描述 |
Amazon RDS 的默认设置 |
Aurora 的默认设置 |
|
在 autovacuum 对一个表进行清理操作之前,该表上必须发生的最小的元组更新或删除操作次数。 |
50 次操作 |
50 次操作 |
|
在 autovacuum 分析一个表之前,该表上必须发生的最小的元组插入、更新或删除操作次数。 |
50 次操作 |
50 次操作 |
|
在 autovacuum 对表进行清理之前,该表中必须修改的元组所占的百分比。 |
0.1 |
0.1 |
|
在 autovacuum 对表进行分析之前,该表中必须修改的元组所占的比例。 |
0.05 |
0.05 |
|
在对表进行清理操作之前,冻结的 ID 的最大有效期,以防止事务 ID 循环问题。 |
2 亿次事务 |
2 亿次事务 |
Autovacuum 会根据特定的阈值公式生成需要处理的表的列表,具体如下。
-
在表格上运行
VACUUM的阈值:vacuum threshold = autovacuum_vacuum_threshold + (autovacuum_vacuum_scale_factor * Total row count of table) -
在表格上运行
ANALYZE的阈值:analyze threshold = autovacuum_analyze_threshold + (autovacuum_analyze_scale_factor * Total row count of table)
对于中小型表,默认值可能就足够用了。但是,经常进行数据修改的大型表中会存在更多的死元组。在这种情况下,autovacuum 可能会频繁地对此表进行处理以进行维护操作,而其他表的维护工作可能会因此被推迟或忽略,直到这个大型表的维护工作完成为止。为避免这种情况,您可以调整下一部分中所述的 autovacuum 参数。
Autovacuum 与内存相关的参数
autovacuum_max_workers
指定可以同时运行的 autovacuum 进程(不包括 autovacuum 启动程序)的最大数量。只有在启动服务器时,才能设置此参数。如果 autovacuum 进程正忙于处理大型表,则此参数有助于对其他表进行清理操作。
maintenance_work_mem
指定维护操作(如 VACUUM、CREATE INDEX 和 ALTER)要使用的最大内存量。在 Amazon RDS 和 Aurora 中,使用公式 GREATEST({DBInstanceClassMemory/63963136*1024},65536) 根据实例类分配内存。autovacuum 运行时,所分配的内存量可能会达到该计算值的最多 autovacuum_max_workers 倍,因此请注意不要把该值定得过高。要对此进行控制,可以单独设置 autovacuum_work_mem。
autovacuum_work_mem
指定要由每个 autovacuum Worker 进程使用的最大内存量。此参数默认为 -1,这表示您应改用 maintenance_work_mem 的值。
有关 autovacuum 内存参数的更多信息,请参阅 Amazon RDS 文档中的为 autovacuum 分配内存。
调整 autovacuum 参数
用户可能需要根据其更新和删除操作来调整 autovacuum 参数。以下参数的设置可以在表级别、实例级别或集群级别进行设置。
集群或实例级别
举个例子,让我们来看一个银行数据库的实例,在这个数据库中,预期会进行持续的数据操纵语言(DML)操作。为了保持数据库的运行状况,您需要针对 Aurora 数据库在集群级别调整 autovacuum 参数,针对 Amazon RDS 数据库在实例级别调整该参数,并且将相同的参数组应用于读取器。在失效转移情况下,应将相同的参数应用于新的写入程序。
表级别
例如,在一个用于食品配送的数据库中,如果需要对名为 orders 的单个表进行持续的 DML 操作,则应该通过使用以下命令在表级别调整 autovacuum_analyze_threshold 参数:
ALTER TABLE <table_name> SET (autovacuum_analyze_threshold = <threshold rows>)
在表格级别使用激进的 autovacuum 设置
由于默认的 autovacuum 设置,具有持续更新和删除操作的示例 orders 表成为了进行清理操作的候选对象。这会导致计划生成不准确以及查询速度变慢。清除膨胀并更新统计信息需要设置表级别的激进式 autovaccum 参数。
要确定设置,请跟踪在此表上运行的查询的持续时间,并确定导致计划变更的 DML 操作所占的百分比。pg_stat_user_tables 视图可帮助您跟踪插入、更新和删除操作。
示例:
假设每当 5% 的 orders 表发生变化时,优化程序就会生成错误的计划。在这种情况下,应将扩展因子阈值更改为 2%,具体如下:
ALTER TABLE orders SET (autovacuum_vacuum_scale_factor = 0.02)
提示
请谨慎选择激进式 autovacuum 设置,以免造成资源的大量消耗。
有关更多信息,请参阅下列内容:
-
自动清理
(PostgreSQL 文档)
为了确保 autovacuum 有效运行,请定期监控死行、磁盘使用情况以及 autovacuum 或 ANALYZE 上一次定期运行的时间。pg_stat_all_tables 视图提供有关每个表(relname)以及表中有多少死元组(n_dead_tup)的信息。
监控每个表(尤其是那些频繁更新的表)中的死元组数量,有助于您判断 autovacuum 进程是否定期移除这些死元组,以便重新利用其占用的磁盘空间,从而提高系统性能。您可以使用以下查询来检查死元组的数量以及上一次对表运行 autovacuum 的时间:
SELECT relname AS TableName,n_live_tup AS LiveTuples,n_dead_tup AS DeadTuples, last_autovacuum AS Autovacuum,last_autoanalyze AS Autoanalyze_FROM pg_stat_user_tables;
优点和限制
Autovacuum 具备下述优点:
-
它会自动移除表格中的膨胀。
-
它可以防止事务 ID 循环。
-
它使数据库统计信息保持最新。
限制:
-
如果查询采用并行处理方式,则 autovacuum 所需的 Worker 进程数量可能会不够。
-
如果 autovacuum 在高峰时段运行,则资源利用率可能会提高。您应该调整参数来处理这个问题。
-
如果表格页面被另一个会话占用,autovacuum 可能会跳过这些页面。
-
Autovacuum 无法访问临时表。