

 从补丁 198 开始，Amazon Redshift 将不再支持创建新的 Python UDF。现有的 Python UDF 将继续正常运行至 2026 年 6 月 30 日。有关更多信息，请参阅[博客文章](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)。

# 对表执行 vacuum 操作
<a name="t_Reclaiming_storage_space202"></a>

Amazon Redshift 可以在后台自动对表进行排序并执行 VACUUM DELETE 操作。要在加载或一系列增量更新操作后清理表，您也可以对整个数据库或对单个表运行 [VACUUM](r_VACUUM_command.md) 命令。

**注意**  
只有拥有必要的表权限的用户才能有效地对表执行 vacuum 操作。如果在没有必需的表权限的情况下运行 VACUUM 操作，该操作将成功完成，但不起任何作用。有关能有效运行 VACUUM 操作的有效表权限列表，请参阅[VACUUM](r_VACUUM_command.md)。  
出于此原因，我们建议根据需要对各个表执行 vacuum 操作。我们也推荐此方法，因为对整个数据库进行 vacuum 操作可能会消耗大量资源。

## 自动表排序
<a name="automatic-table-sort"></a>

Amazon Redshift 在后台自动对数据进行排序以按照其排序键顺序保留表数据。Amazon Redshift 将跟踪您的扫描查询以确定表的哪些部分将从排序中受益。Amazon Redshift 还会跟踪来自并发扩展集群的扫描查询。对于使用 Amazon Redshift 数据共享的多集群架构，Amazon Redshift 还会跟踪来自数据网格中使用者集群/工作组（包括不同区域的集群/工作组）的扫描查询。系统将来自主集群、并发扩展集群和使用者集群中的扫描统计数据聚合在一起，来确定表的哪些部分可以从排序中获益。

根据系统上的负载，Amazon Redshift 自动启动排序操作。此自动排序减少了运行 VACUUM 命令以按排序键顺序保留数据的需求。如果您需要按排序键顺序对数据进行完全排序（例如，在加载大量数据之后），则您仍可以手动运行 VACUUM 命令。要通过运行 VACUUM SORT 来确定您的表是否将受益，请监控 `vacuum_sort_benefit` 中的 [SVV\$1TABLE\$1INFO](r_SVV_TABLE_INFO.md) 列。

Amazon Redshift 跟踪在每个表上使用排序键的扫描查询。Amazon Redshift 估计每个表（如果表已完全排序）在数据扫描和筛选方面的最大改进百分比。此估计值在 `vacuum_sort_benefit` 中的 [SVV\$1TABLE\$1INFO](r_SVV_TABLE_INFO.md) 列中可见。您可以将此列与 `unsorted` 列结合使用，确定查询何时可以从手动对表运行 VACUUM SORT 中受益。`unsorted` 列反映表的物理排序顺序。`vacuum_sort_benefit` 列指定通过手动运行 VACUUM SORT 对表进行排序的影响。

例如，请考虑以下查询：

```
select "table", unsorted,vacuum_sort_benefit from svv_table_info order by 1;
```

```
 table | unsorted | vacuum_sort_benefit 
-------+----------+---------------------
 sales |    85.71 |                5.00
 event |    45.24 |               67.00
```

对于表“sales”，即使该表的物理未排序项约为 86%，其对查询性能的影响也仅为 5%。这可能是因为查询只访问表的一小部分内容，也可能是因为访问表的查询几近于无。对于表“event”，该表的物理未排序项约为 45%。不过，67% 的查询性能影响表明查询访问了表的更大部分内容，或者访问表的查询的数量很多。表“event”可能会从运行 VACUUM SORT 中受益。

## 自动 vacuum 删除
<a name="automatic-table-delete"></a>

执行 delete 操作时，会将行标记为删除，但不会删除。Amazon Redshift 会根据数据库表中已删除的行数在后台自动运行 VACUUM DELETE 操作。Amazon Redshift 安排 VACUUM DELETE 在负载减少期间运行，并在高负载期间暂停操作。

**Topics**
+ [自动表排序](#automatic-table-sort)
+ [自动 vacuum 删除](#automatic-table-delete)
+ [vacuum 频率](#vacuum-frequency)
+ [排序阶段和合并阶段](#vacuum-stages)
+ [vacuum 阈值](#vacuum-sort-threshold)
+ [vacuum 类型](#vacuum-types)
+ [最大程度地减少 vacuum 次数](vacuum-managing-vacuum-times.md)

## vacuum 频率
<a name="vacuum-frequency"></a>

您应按照所需的频率执行 vacuum 操作以保持一致的查询性能。在确定运行 VACUUM 命令的频率时，请考虑以下因素：
+ 在预计集群上的活动最少的时间段（例如，夜晚或指定的数据库管理时段）内运行 VACUUM。
+ 在维护时段之外运行 VACUUM 命令。有关更多信息，请参阅[计划维护时段](https://docs.aws.amazon.com/redshift/latest/dg/c_best-practices-avoid-maintenance.html)。
+ 大型未排序区域将导致更长的 vacuum 时间。如果您延迟 vacuum 操作，则 vacuum 操作将需要更长的时间，因为需要识别更多数据。
+ VACUUM 是 I/O 密集型操作，因此，完成 vacuum 操作所需的时间越长，它对您的集群上运行的并发查询和其他数据库操作的影响就越大。
+ 对于使用交错排序的表，VACUUM 花费的时间更长。要评估是否必须对交错的表重新排序，请查询 [SVV\$1INTERLEAVED\$1COLUMNS](r_SVV_INTERLEAVED_COLUMNS.md) 视图。

## 排序阶段和合并阶段
<a name="vacuum-stages"></a>

Amazon Redshift 按照两个阶段执行 vacuum 操作：首先，它会对未排序区域中的行进行排序；然后，如有必要，会将表结尾处的新排序的行与现有行合并。在对大型表执行 vacuum 操作时，vacuum 操作将在合并后继续一系列步骤（包括增量排序）。如果操作失败，或者如何 Amazon Redshift 在 vacuum 操作期间脱机，已部分执行 vacuum 操作的表或数据库将处于一致状态，但您必须手动重启 vacuum 操作。增量排序将丢失，但不需要再次对失败前已提交的合并行执行 vacuum 操作。如果未排序区域较大，则浪费的时间可能更多。有关排序阶段和合并阶段的更多信息，请参阅[减少合并的行数](vacuum-managing-vacuum-times.md#vacuum-managing-volume-of-unmerged-rows)。

在对表执行 vacuum 操作时，用户可以访问表。您可以在对表执行 vacuum 操作的同时执行查询和写入操作，但如果 DML 和 vacuum 操作同时运行，则二者可能花费更长时间。如果您在 vacuum 操作期间执行 UPDATE 和 DELETE 语句，则系统性能可能会降低。增量合并会临时阻止并发 UPDATE 和 DELETE 操作，而 UPDATE 和 DELETE 反过来会临时阻止对受影响的表执行增量合并步骤。在对表执行完 vacuum 操作前，DDL 操作（例如 ALTER TABLE）将被阻止。

**注意**  
VACUUM 的各种修饰符控制它的工作方式。您可以使用它们来根据当前需求定制 vacuum 操作。例如，使用 VACUUM RECLUSTER 可通过不执行完全合并操作来缩短 vacuum 操作。有关更多信息，请参阅 [VACUUM](r_VACUUM_command.md)。

## vacuum 阈值
<a name="vacuum-sort-threshold"></a>

默认情况下，当任意表中有 95% 的行已有序时，VACUUM 会为该表跳过排序阶段。跳过排序阶段能够显著提高 VACUUM 的性能。要更改某个表的默认排序阈值，请在运行 VACUUM 命令时包含表名称和 TO *threshold* PERCENT 参数。

## vacuum 类型
<a name="vacuum-types"></a>

有关不同 vacuum 类型的信息，请参阅[VACUUM](r_VACUUM_command.md)。

# 最大程度地减少 vacuum 次数
<a name="vacuum-managing-vacuum-times"></a>

 Amazon Redshift 自动对数据进行排序，并在后台运行 VACUUM DELETE。这减少了运行 VACUUM 命令的需要。Vacuum 可能是一个耗时的过程。根据数据的性质，建议您采用以下做法来最大程度地减少 vacuum 次数。

**Topics**
+ [决定是否重建索引](#r_vacuum-decide-whether-to-reindex)
+ [减少未排序区域的大小](#r_vacuum_diskspacereqs)
+ [减少合并的行数](#vacuum-managing-volume-of-unmerged-rows)
+ [按排序键顺序加载数据](#vacuum-load-in-sort-key-order)
+ [使用时间序列表来减少存储的数据](#vacuum-time-series-tables)

## 决定是否重建索引
<a name="r_vacuum-decide-whether-to-reindex"></a>

通常，您可以使用交错排序样式来显著提高查询性能，但是随着时间的推移，如果排序键列中值的分配更改，性能可能会下降。

最初使用 COPY 或 CREATE TABLE AS 加载空交错表时，Amazon Redshift 自动构建交错索引。如果您最初使用 INSERT 加载交错表，则需要在之后运行 VACUUM REINDEX 以初始化交错索引。

随着时间的推移，在添加带有新排序键值的行后，如果排序键列中值的分布发生更改，性能可能会下降。如果新行主要处于现有排序键值的范围内，则不必重建索引。可以运行 VACUUM SORT ONLY 或 VACUUM FULL 恢复排序顺序。

查询引擎能够使用排序顺序高效地选择处理查询所需扫描的数据块。对于交错排序，Amazon Redshift 将分析排序键列值以确定最佳排序顺序。如果键值的分配在添加行时发生更改或偏移，则排序策略将不再是最佳的排序策略，并且排序的性能优势也会减小。要重新分析排序键分配，您可以运行 VACUUM REINDEX。重建索引操作非常耗时，因此，要决定表是否将从重建索引中获益，请查询 [SVV\$1INTERLEAVED\$1COLUMNS](r_SVV_INTERLEAVED_COLUMNS.md) 视图。

例如，以下查询将显示使用交错排序键的表的详细信息。

```
select tbl as tbl_id, stv_tbl_perm.name as table_name, 
col, interleaved_skew, last_reindex
from svv_interleaved_columns, stv_tbl_perm
where svv_interleaved_columns.tbl = stv_tbl_perm.id
and interleaved_skew is not null;


 tbl_id | table_name | col | interleaved_skew | last_reindex
--------+------------+-----+------------------+--------------------
 100048 | customer   |   0 |             3.65 | 2015-04-22 22:05:45
 100068 | lineorder  |   1 |             2.65 | 2015-04-22 22:05:45
 100072 | part       |   0 |             1.65 | 2015-04-22 22:05:45
 100077 | supplier   |   1 |             1.00 | 2015-04-22 22:05:45
(4 rows)
```

`interleaved_skew` 的值是一个比率，指示偏移量。值 1 表示无偏移。如果偏移大于 1.4，VACUUM REINDEX 通常会提高性能，除非偏移是基础集中固有的。

您可以使用 `last_reindex` 中的数据值来确定自上次重建索引以来经历的时间。

## 减少未排序区域的大小
<a name="r_vacuum_diskspacereqs"></a>

在将大量新数据加载到已包含数据的表中时，或在例行维护操作不包含对表进行的 vacuum 操作时，未排序区域将增大。要避免长时间运行的 vacuum 操作，请使用以下做法：
+ 定期运行 vacuum 操作。

  如果您以较小增量加载您的表（例如，表示表中行总数的一小部分的日常更新），定期运行 VACUUM 将帮助确保各个 vacuum 操作快速执行。
+ 首先运行最大加载。

  如果您需要使用多个 COPY 操作加载新表，请首先运行最大加载。当您运行到新的或截断的表中的初始加载时，所有数据将直接加载到已排序区域，因此无需执行 vacuum 操作。
+ 截断表而不是删除所有行。

  从表中删除行不会回收行占用的空间，除非您执行 vacuum 操作；不过，截断表将清空表并回收磁盘空间，因此无需执行 vacuum 操作。或者，请删除表并重新创建它。
+ 截断或删除测试表。

  如果您正在将少量行加载到表中以进行测试，请在完成此操作后不要删除这些行。相反，作为后续生产加载操作的一部分，请截断表并重新加载这些行。
+ 执行深层复制。

  如果使用复合排序键的表具有大型未排序区域，则深层复制要比 vacuum 快得多。深层复制将使用批量插入来重新创建并重新填充表，这将自动对表进行重新排序。如果表拥有大型未排序区域，深层复制将比真空化快得多。这样做的代价是，您不能在深层复制操作过程中进行并行更新，但可以在真空化时这样做。有关更多信息，请参阅 [设计查询的 Amazon Redshift 最佳实践](c_designing-queries-best-practices.md)。

## 减少合并的行数
<a name="vacuum-managing-volume-of-unmerged-rows"></a>

如果 vacuum 操作需要将新行合并到表的已排序区域，vacuum 所需的时间将随表的增大而增多。您可以通过减少必须合并的行数来提高 vacuum 性能。

在执行 vacuum 操作之前，表包含一个已排序区域（位于表开头处），后跟一个未排序区域（当添加或更新行时，该区域将增大）。如果 COPY 操作添加一组行，则这组新行在添加到表结尾处的未排序区域时将基于排序键进行排序。新行将在其自己的集合中进行排序，而不是在未排序区域内进行排序。

下图说明了两次连续 COPY 操作后的未排序区域，其中排序键为 CUSTID。为简便起见，此示例显示一个复合排序键，但相同的原则适用于交错排序键，只不过未排序区域对交错表的影响更大。

![\[一个未排序的表，其中保存着两次 COPY 操作的记录。\]](http://docs.aws.amazon.com/zh_cn/redshift/latest/dg/images/vacuum-unsorted-region.png)


Vacuum 将按两个阶段还原复表的排序顺序：

1. 将未排序区域归入新排序的区域。

   第一个阶段的成本相对较低，因为仅重写未排序区域。如果新排序区域的排序键值的范围大于现有范围，则仅需要重写新行即可完成 vacuum。例如，如果已排序区域包含的 ID 值介于 1 和 500 之间，并且后续复制操作将添加大于 500 的键值，则仅需重写未排序区域。

1. 将新排序的区域与之前排序的区域合并。

   如果新排序的区域中的键与已排序区域中的键重叠，则 VACUUM 需要合并这些行。从新排序区域（最低排序键处）的开头开始，vacuum 会将从之前排序的区域和新排序的区域中的合并行写入一组新数据块。

新排序键范围与现有排序键重叠的程度将决定之前排序的区域需要被重写的程度。如果未排序键遍布于现有排序范围中，则 vacuum 可能需要重写表的现有部分。

下图说明 vacuum 如何对添加到排序键为 CUSTID 的表中的行进行排序和合并。由于每个复制操作将添加一组键值与现有键重叠的新行，因此几乎需要重写整个表。该图显示单一排序和合并，但在实践中，大型 vacuum 包含一系列增量排序和合并步骤。

![\[分两步对示例表进行 VACUUM 操作。首先对新行进行排序，然后将其与现有行合并。\]](http://docs.aws.amazon.com/zh_cn/redshift/latest/dg/images/vacuum-unsorted-region-sort-merge.png)


如果一组新行中的排序键范围与现有键的范围重叠，则合并阶段的成本将继续随表的增大与表大小成比例的增长，而排序阶段的成本与未排序区域的大小成正比。在这种情况下，合并阶段的成本远远超过排序阶段的成本，如下图所示。

![\[图中显示了当新行的排序键与现有行重叠时，合并阶段的成本变得更高。\]](http://docs.aws.amazon.com/zh_cn/redshift/latest/dg/images/vacuum-example-merge-region-grows.png)


要确定已重新合并的表的比例，请在 vacuum 操作完成后查询 SVV\$1VACUUM\$1SUMMARY。以下查询表明，在 CUSTSALES 随时间的推移而增大时，六个连续 vacuum 操作的效果。

```
select * from svv_vacuum_summary
where table_name = 'custsales';


 table_name | xid  | sort_      | merge_     | elapsed_   | row_  | sortedrow_ | block_  | max_merge_
            |      | partitions | increments | time       | delta | delta      | delta   | partitions
 -----------+------+------------+------------+------------+-------+------------+---------+---------------
  custsales | 7072 |          3 |          2 |  143918314 |     0 |   88297472 |   1524  |      47
  custsales | 7122 |          3 |          3 |  164157882 |     0 |   88297472 |    772  |      47
  custsales | 7212 |          3 |          4 |  187433171 |     0 |   88297472 |    767  |      47
  custsales | 7289 |          3 |          4 |  255482945 |     0 |   88297472 |    770  |      47
  custsales | 7420 |          3 |          5 |  316583833 |     0 |   88297472 |    769  |      47
  custsales | 9007 |          3 |          6 |  306685472 |     0 |   88297472 |    772  |      47
 (6 rows)
```

merge\$1increments 列指明了为每个 vacuum 操作合并的数据量。如果连续 vacuum 操作的合并增量的数量按表大小增长的比例增加，它表示每个 vacuum 操作重新合并的表中的行数正在增加，因为现有排序区域和新排序区域重叠。

## 按排序键顺序加载数据
<a name="vacuum-load-in-sort-key-order"></a>

如果您使用 COPY 命令按排序键顺序加载数据，可能会减少甚至消除对 vacuum 的需求。

当满足以下所有条件时，COPY 会向表的有序区域自动添加新行：
+ 表使用了只有一个排序列的复合排序键。
+ 排序列 NOT NULL。
+ 表 100% 有序或为空。
+ 所有新行的排序顺序均优先于现有行，包括标记为要删除的行。在此实例中，Amazon Redshift 使用排序键的前八个字节来确定排序顺序。
+  COPY 命令未触发特定负载优化。加载大量数据时，Amazon Redshift 可能会通过创建新的排序分区（而不是向表的排序区域添加行）来优化性能。

例如，假设您有一个使用客户 ID 和时间记录客户事件的表。如果按客户 ID 进行排序，则增量加载添加的新行的排序键范围可能会与现有范围重叠（如上一个示例中所示），从而导致昂贵的 vacuum 操作。

如果您将排序键设置为时间戳列，新行将按排序顺序追加到表的结尾（如下图所示），从而减少甚至消除对 vacuum 的需求。

![\[使用时间戳列作为排序键的表，获取无需排序的新记录。\]](http://docs.aws.amazon.com/zh_cn/redshift/latest/dg/images/vacuum-unsorted-region-date-sort.png)


## 使用时间序列表来减少存储的数据
<a name="vacuum-time-series-tables"></a>

如果您将数据保留滚动时段，请使用一系列表，如下图所示。

![\[五张表，其中包含五个季度的数据。删除最旧的表以保持一年的滚动时间。\]](http://docs.aws.amazon.com/zh_cn/redshift/latest/dg/images/vacuum-example-unsorted-region-copy-time-series.png)


每当添加一组数据时创建一个新表，然后删除系列中最旧的表。您将获得双重好处：
+ 避免增加删除行的成本，因为 DROP TABLE 操作比大规模 DELETE 更高效。
+ 如果按时间戳对表进行排序，则不需要执行 vacuum 操作。如果每个表包含一个月的数据，则 vacuum 最多必须重写一个月的数据，即使表不是按时间戳排序的也是如此。

您可以创建 UNION ALL 视图供报告查询使用，从而隐藏数据存储在多个表中的事实。如果查询按排序键进行筛选，则查询计划程序可高效地跳过未使用的所有表。UNION ALL 对其他类型的查询可能不太高效，因此您应在所有使用表的查询的环境中评估查询性能。