

# 通过清理回收存储空间
<a name="limitless-vacuum"></a>

PostgreSQL 多版本并发控制（MVCC）通过保存已更新或已删除行的内部副本，帮助保持数据完整性，直到事务提交或回滚。这些副本也称为*元组*，如果不定期清理，可能会导致表膨胀。PostgreSQL 实例按事务 ID 对事务进行排序，而 PostgreSQL 使用基于事务 ID 的 MVCC 来控制元组的可见性并提供事务隔离。每个事务都会建立数据快照，每个元组都有一个版本。快照和版本均基于事务 ID。

为了清理数据，`VACUUM` 实用程序在 PostgreSQL 中执行了四个关键功能：
+ `VACUUM` – 移除过期的行版本，使空间可供重复使用。
+ `VACUUM FULL` – 通过移除死行版本并压缩表来提供完整的碎片整理，从而减小表大小并提高效率。
+ `VACUUM FREEZE` – 通过将较旧的行版本标记为冻结，防止事务 ID 环绕问题。
+ `VACUUM ANALYZE` – 移除死行版本并更新数据库的查询计划统计数据。它是 `VACUUM` 和 `ANALYZE` 函数的组合。有关 Aurora PostgreSQL Limitless Database 中 `ANALYZE` 工作原理的更多信息，请参阅[ANALYZE](limitless-reference.DML-limitations.md#limitless-reference.DML-limitations.ANALYZE)。

 与 MVCC 一样，在 Aurora PostgreSQL 中进行清理是基于事务 ID 的。如果在清理开始时有正在进行的事务，则不会移除该事务仍然可见的行。

有关 `VACUUM` 实用程序的更多信息，请参阅 PostgreSQL 文档中的 [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)。有关 Aurora PostgreSQL Limitless Database 中 `VACUUM` 支持的更多信息，请参阅 [VACUUM](limitless-reference.DML-limitations.md#limitless-reference.DML-limitations.VACUUM)。

**Topics**
+ [AUTOVACUUM](#limitless-autovacuum)
+ [Aurora PostgreSQL Limitless Database 中基于时间的清理](#limitless-vacuum.time-based)
+ [使用数据库统计数据进行清理](#limitless-vacuum.stats)
+ [Aurora PostgreSQL 和 Aurora PostgreSQL Limitless Database 在清理行为上的差异](#limitless-vacuum-limitations)

## AUTOVACUUM
<a name="limitless-autovacuum"></a>

Aurora PostgreSQL 使用 `VACUUM` 和 `AUTOVACUUM` 实用程序来移除不需要的元组。`AUTOVACUUM` 和手动 `VACUUM` 的底层机制相同；唯一的区别是自动化。

Aurora PostgreSQL 和 Aurora PostgreSQL Limitless Database 中的 `AUTOVACUUM` 是 `VACUUM` 和 `ANALYZE` 实用程序的组合。`AUTOVACUUM` 根据预定义的规则（例如死元组的百分比和插入次数）确定要清理哪些数据库和表。

例如，`AUTOVACUUM` 会定期“唤醒”以执行清理。间隔时间由 `autovacuum_naptime` 参数控制。默认值为 1 分钟。Aurora PostgreSQL Limitless Database 的默认值 `AUTOVACUUM` 和 `VACUUM` 配置参数与 Aurora PostgreSQL 相同。

如果启用 `AUTOVACUUM` 进程守护程序，只要表的内容发生足够大的变化，它就会自动发出 `ANALYZE` 命令。在 Aurora PostgreSQL Limitless Database 中，`AUTOVACUUM` 会在路由器和分片上发出 `ANALYZE`。

有关 `AUTOVACUUM` 进程守护程序和与 `AUTOVACUUM` 关联的表存储参数的更多信息，请参阅 PostgreSQL 文档中的 [The autovacuum daemon](https://www.postgresql.org/docs/current/routine-vacuuming.html#AUTOVACUUM ) 和 [Storage parameters](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html)。

## Aurora PostgreSQL Limitless Database 中基于时间的清理
<a name="limitless-vacuum.time-based"></a>

Aurora PostgreSQL Limitless Database 是一个分布式系统，这意味着一个事务可以涉及多个实例。因此，基于事务 ID 的可见性不适用。相反，Aurora PostgreSQL Limitless Database 使用*基于时间*的可见性，因为事务 ID 无法在不同实例之间“统一”，但时间可以在不同实例之间“统一”。每个事务快照和每个元组版本都遵循时间而不是事务 ID。更具体地说，事务快照有快照开始时间，元组有创建时间（发生 `INSERT` 或 `UPDATE` 时）和删除时间（发生 `DELETE` 时）。

为了保持数据库分片组中实例间的数据一致性，Aurora PostgreSQL Limitless Database 必须确保清理不会移除数据库分片组中任何活动事务仍可见的任何元组。因此，Aurora PostgreSQL Limitless Database 中的清理也是基于时间的。`VACUUM` 的其他方面保持不变，包括要在特定表上运行 `VACUUM`，用户必须有访问该表的权限。

**注意**  
我们强烈建议您不要让事务长时间处于开放状态。  
基于时间的清理会比基于事务 ID 的清理消耗更多的内存。

以下示例说明了基于时间的清理的工作原理。

1. 客户表分布在四个分片上。

1. 事务 1 从可重复读取开始，并且仅针对一个分片（分片 1）。此事务仍处于开放状态。

   事务 1 早于其后开始的任何其他事务。

1. 事务 2 稍后开始，从表中删除所有元组，然后提交。

1. 如果 `AUTOVACUUM` 或手动 `VACUUM` 尝试清理死元组（由于事务 2 而死亡），它不会移除任何内容。

   这不仅适用于分片 1，也适用于分片 2–4，因为事务 1 可能仍需要访问这些元组。由于 MVCC，它们仍然对事务 1 可见。

最后一步是通过同步实现的，因此所有分片都知道事务 1，即使事务 1 并未触及所有分片。

## 使用数据库统计数据进行清理
<a name="limitless-vacuum.stats"></a>

要获取有关可能需要清理的元组的信息，请使用 [limitless\$1stat\$1all\$1tables](limitless-monitoring-views.md#limitless_stat_all_tables) 视图，其工作原理与 [pg\$1stat\$1all\$1tables](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ALL-TABLES-VIEW) 类似。以下示例查询了视图。

```
SELECT * FROM rds_aurora.limitless_stat_all_tables WHERE relname LIKE '%customer%';
```

同样，对于数据库统计数据，请使用 [limitless\$1stat\$1database](limitless-monitoring-views.md#limitless_stat_database) 代替 [pg\$1stat\$1database](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-DATABASE-VIEW)，使用 [limitless\$1stat\$1activity](limitless-monitoring-views.md#limitless_stat_activity) 代替 [pg\$1stat\$1activity](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW)。

要检查表磁盘使用情况，请使用 [limitless\$1stat\$1relation\$1sizes](limitless-monitoring-functions.md#limitless_stat_relation_sizes) 函数，其工作原理与 [pg\$1relation\$1size](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-DBOBJECT) 类似。以下示例查询函数。

```
SELECT * FROM rds_aurora.limitless_stat_relation_sizes('public','customer');
```

要在 Aurora PostgreSQL Limitless Database 上跟踪 `VACUUM` 操作的进度，请使用 [limitless\$1stat\$1progress\$1vacuum](limitless-monitoring-views.md#limitless_stat_progress_vacuum) 视图，而不是 [pg\$1stat\$1progress\$1vacuum](https://www.postgresql.org/docs/15/progress-reporting.html#VACUUM-PROGRESS-REPORTING)。以下示例查询了视图。

```
SELECT * FROM rds_aurora.limitless_stat_progress_vacuum;
```

有关更多信息，请参阅[Aurora PostgreSQL Limitless Database 视图](limitless-monitoring-views.md) 和[Aurora PostgreSQL Limitless Database 函数](limitless-monitoring-functions.md)。

## Aurora PostgreSQL 和 Aurora PostgreSQL Limitless Database 在清理行为上的差异
<a name="limitless-vacuum-limitations"></a>

Aurora PostgreSQL 和 Aurora PostgreSQL Limitless Database 在清理工作原理方面的一些其他区别如下：
+ Aurora PostgreSQL 对事务 ID 执行 `VACUUM` 操作，直到最早的正在进行的事务。如果数据库中没有正在进行的事务，则 `VACUUM` 执行该操作直到最后一个事务。
+ Aurora PostgreSQL Limitless Database 每 10 秒同步一次最早的时间快照。因此，`VACUUM` 可能不会对过去 10 秒内运行的任何事务执行该操作。

有关 Aurora PostgreSQL Limitless Database 中 `VACUUM` 支持的信息，请参阅 [Aurora PostgreSQL Limitless Database 参考Limitless Database 参考](limitless-reference.md)中的 [VACUUM](limitless-reference.DML-limitations.md#limitless-reference.DML-limitations.VACUUM)。