

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 自动清理和分析表格
<a name="autovacuum"></a>

Autovacuum 是一个进程守护程序（也就是说，它在后台运行），它会自动 *vacuum*（清理）死元组，回收存储空间并收集统计信息。它会检查数据库中是否有膨胀的表，并清除膨胀以重新利用这些空间。它会监控数据库表和索引，并在这些表或索引的更新或删除操作达到特定阈值后，将它们添加到 vacuum 作业中。

Autovacuum 通过自动执行 PostgreSQL `VACUUM` 和 `ANALYZE` 命令来管理 vacuum 操作。`VACUUM` 从表中移除膨胀并回收空间，同时 `ANALYZE` 更新统计信息，使优化程序能够制定有效的计划。`VACUUM` 还执行一项名为 *vacuum 冻结*的主要任务，以防止数据库中出现事务 ID 循环问题。数据库中每一个被更新的行都会从 PostgreSQL 事务控制机制中获得一个事务 ID。它们 IDs 控制该行对其他并发事务的可见性。事务 ID 是一个 32 位的数字。20亿 IDs 人总是留在可见的过去。剩余 IDs 的（约22亿）用于将来将要进行的交易，并且隐藏在当前交易之外。PostgreSQL 需要偶尔清理和*冻结*旧行，以防止事务回绕并在创建新事务时使旧的现有行不可见。有关更多信息，请参阅 PostgreSQL 文档中的[防止事务 ID 重现故障](https://www.postgresql.org/docs/current/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND)。

建议使用 Autovacuum 且它在默认情况下处于启用状态。其参数包括以下选项：


|  |  |  |  | 
| --- |--- |--- |--- |
| **参数** | **描述** | **Amazon RDS 的默认设置** | **Aurora 的默认设置** | 
| `autovacuum_vacuum_threshold` | 在 autovacuum 对一个表进行清理操作之前，该表上必须发生的最小的元组更新或删除操作次数。 | 50 次操作 | 50 次操作 | 
| `autovacuum_analyze_threshold` | 在 autovacuum 分析一个表之前，该表上必须发生的最小的元组插入、更新或删除操作次数。 | 50 次操作 | 50 次操作 | 
| `autovacuum_vacuum_scale_factor` | 在 autovacuum 对表进行清理之前，该表中必须修改的元组所占的百分比。 | 0.1 | 0.1 | 
| `autovacuum_analyze_scale_factor` | 在 autovacuum 对表进行分析之前，该表中必须修改的元组所占的比例。 | 0.05 | 0.05 | 
| `autovacuum_freeze_max_age` | 清空表 IDs 之前的最大冻结期限，以防止事务 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 与内存相关的参数
<a name="autovacuum-parameters"></a>

**`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 分配内存](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.WorkMemory)。

## 调整 autovacuum 参数
<a name="autovacuum-tuning"></a>

用户可能需要根据其更新和删除操作来调整 autovacuum 参数。以下参数的设置可以在表级别、实例级别或集群级别进行设置。

### 集群或实例级别
<a name="autovacuum-cluster-instance"></a>

举个例子，让我们来看一个银行数据库的实例，在这个数据库中，预期会进行持续的数据操纵语言（DML）操作。为了保持数据库的运行状况，您需要针对 Aurora 数据库在集群级别调整 autovacuum 参数，针对 Amazon RDS 数据库在实例级别调整该参数，并且将相同的参数组应用于读取器。在失效转移情况下，应将相同的参数应用于新的写入程序。

### 表级别
<a name="autovacuum-table"></a>

例如，在一个用于食品配送的数据库中，如果需要对名为 `orders` 的单个表进行持续的 DML 操作，则应该通过使用以下命令在表级别调整 `autovacuum_analyze_threshold` 参数：

```
ALTER TABLE <table_name> SET (autovacuum_analyze_threshold = <threshold rows>)
```

### 在表格级别使用激进的 autovacuum 设置
<a name="autovacuum-table-aggressive"></a>

由于默认的 autovacuum 设置，具有持续更新和删除操作的示例 `orders` 表成为了进行清理操作的候选对象。这会导致计划生成不准确以及查询速度变慢。清除膨胀并更新统计信息需要设置表级别的激进式 autovaccum 参数。

要确定设置，请跟踪在此表上运行的查询的持续时间，并确定导致计划变更的 DML 操作所占的百分比。`pg_stat_user_tables` 视图可帮助您跟踪插入、更新和删除操作。

示例：

假设每当 5% 的 `orders` 表发生变化时，优化程序就会生成错误的计划。在这种情况下，应将扩展因子阈值更改为 2%，具体如下：

```
ALTER TABLE orders SET (autovacuum_vacuum_scale_factor = 0.02)
```

**提示**  
请谨慎选择激进式 autovacuum 设置，以免造成资源的大量消耗。

有关更多信息，请参阅下列内容：
+ [了解 Amazon RDS for PostgreSQL AWS 环境中的自动真空](https://aws.amazon.com/blogs/database/understanding-autovacuum-in-amazon-rds-for-postgresql-environments/)（博客文章）
+ [自动清理](https://www.postgresql.org/docs/17/runtime-config-autovacuum.html)（PostgreSQL 文档）
+ [调整亚马逊 RDS 和亚马逊 Aurora 中的 PostgreSQL 参数（规范](https://docs.aws.amazon.com//prescriptive-guidance/latest/tuning-postgresql-parameters/)性指南AWS ）

为了确保 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;
```

## 优点和限制
<a name="autovacuum_limitations"></a>

Autovacuum 具备下述优点：
+ 它会自动移除表格中的膨胀。
+ 它可以防止事务 ID 循环。
+ 它使数据库统计信息保持最新。

限制：
+ 如果查询采用并行处理方式，则 autovacuum 所需的 Worker 进程数量可能会不够。
+ 如果 autovacuum 在高峰时段运行，则资源利用率可能会提高。您应该调整参数来处理这个问题。
+ 如果表格页面被另一个会话占用，autovacuum 可能会跳过这些页面。
+ Autovacuum 无法访问临时表。