VACUUM
VACUUM — 垃圾收集并按需分析数据库
大纲
VACUUM [ (option[, ...] ) ] [table_and_columns[, ...] ] 其中option可以是下列之一: FREEZE [boolean] VERBOSE [boolean] ANALYZE [boolean] DISABLE_PAGE_SKIPPING [boolean] SKIP_LOCKED [boolean] INDEX_CLEANUP { AUTO | ON | OFF } PROCESS_MAIN [boolean] PROCESS_TOAST [boolean] TRUNCATE [boolean] PARALLELintegerSKIP_DATABASE_STATS [boolean] ONLY_DATABASE_STATS [boolean] BUFFER_USAGE_LIMITsizeFULL [boolean] 其中table_and_columns是: [ ONLY ]table_name[ * ] [ (column_name[, ...] ) ]
描述
VACUUM 回收死元组占用的存储空间。在正常的
PostgreSQL 运行中,被删除或因更新而过时的元组并不会从其表中物理移除;它们会一直保留,直到执行
VACUUM。因此有必要定期执行
VACUUM,尤其是对频繁更新的表。
如果没有给出 table_and_columns
列表,VACUUM 会处理当前数据库中当前用户有权清理的每个表和物化视图。如果给出了列表,VACUUM 则只处理其中列出的表。
VACUUM ANALYZE 会对每个选定表先执行
VACUUM,再执行 ANALYZE。这种便捷的组合形式很适合例行维护脚本使用。关于其处理细节,参见 ANALYZE。
普通的 VACUUM(不带 FULL)只是回收空间并使其可被重用。这种形式的命令可以与表的正常读写并行运行,因为它不会获得独占锁。不过,在大多数情况下,额外空间不会返还给操作系统;它只是保留在同一张表内供再次使用。它还允许利用多个 CPU 来处理索引。这项功能称为 Parallel Vacuum。如需禁用该功能,可以使用 PARALLEL 选项并将并行工作进程数指定为零。VACUUM FULL 会把表的全部内容重写到一个没有额外空闲空间的新磁盘文件中,从而让未使用的空间能够返还给操作系统。这种形式要慢得多,并且在处理每个表时都需要
ACCESS EXCLUSIVE 锁。
参数
FREEZE#选择激进的元组“冻结”。指定
FREEZE等价于执行一个将 vacuum_freeze_min_age 和 vacuum_freeze_table_age 参数设为零的VACUUM。在表被重写时总会执行激进冻结,因此指定了FULL时,这个选项就是多余的。VERBOSE#为每个表以
INFO级别输出详细的清理活动报告。ANALYZE#更新规划器用来确定查询最高效执行方式的统计信息。
DISABLE_PAGE_SKIPPING#通常,
VACUUM会根据可见性映射跳过某些页面。已知其中所有元组都已冻结的页面总是可以跳过,而已知其中所有元组都对所有事务可见的页面,也可以跳过,除非正在执行激进清理。此外,除非正在执行激进清理,为了避免等待其他会话结束对页面的使用,也可能会跳过某些页面。此选项会禁用所有跳页行为,只应在怀疑可见性映射内容存在问题时使用;而这种情况应当只会在硬件或软件问题导致数据库损坏时发生。SKIP_LOCKED#指定
VACUUM在开始处理某个关系时,不要等待任何冲突锁被释放:如果某个关系无法在无需等待的情况下立即获得锁,就跳过该关系。请注意,即使使用了此选项,VACUUM在打开该关系的索引时仍可能发生阻塞。此外,VACUUM ANALYZE在从分区、继承子表和某些类型的外部表获取样本行时,仍然可能发生阻塞。还有,虽然VACUUM通常会处理指定分区表的全部分区,但如果该分区表上存在冲突锁,此选项会导致VACUUM跳过所有分区。INDEX_CLEANUP#通常,当表中的死元组很少时,
VACUUM会跳过索引清理。在这种情况下,处理该表全部索引的代价预计会远高于删除死索引元组带来的收益。当表中存在多于零个死元组时,此选项可用于强制VACUUM处理索引。默认值是AUTO,这允许VACUUM在适当时跳过索引清理。如果INDEX_CLEANUP设为ON,VACUUM将保守地从索引中移除所有死元组。这对于兼容 PostgreSQL 早期版本可能很有用,因为在那些版本中这是标准行为。INDEX_CLEANUP也可以设为OFF,以强制VACUUM总是跳过索引清理,即使表中有很多死元组也是如此。当需要让VACUUM尽可能快地运行,以避免临近的事务 ID 回卷时,这可能会有用(参见第 24.1.5 节)。不过,由 vacuum_failsafe_age 控制的回卷失效保护机制通常会自动触发,以避免事务 ID 回卷失败,因此一般应优先依赖该机制。如果不定期执行索引清理,性能可能会受到影响,因为随着表被修改,索引会积累死元组,而表本身也会积累在索引清理完成前无法移除的死行指针。对没有索引的表,此选项没有效果;如果使用了
FULL选项,它也会被忽略。它对事务 ID 回卷失效保护机制同样没有影响。当该机制被触发时,即使INDEX_CLEANUP设为ON,也会跳过索引清理。PROCESS_MAIN#指定
VACUUM应尝试处理主关系。这通常是期望的行为,也是默认行为。当只需要清理某个关系对应的TOAST表时,将此选项设为 false 可能会有用。PROCESS_TOAST#指定
VACUUM应尝试处理每个关系对应的TOAST表(如果存在)。这通常是期望的行为,也是默认行为。当只需要清理主关系时,将此选项设为 false 可能会有用。使用FULL选项时必须启用此选项。TRUNCATE#指定
VACUUM应尝试截去表末尾的空页,使这些被截断页面占用的磁盘空间能够返还给操作系统。通常这是期望的行为,也是默认行为,除非 vacuum_truncate 被设为 false,或者待清理表的vacuum_truncate选项被设为 false。将此选项设为 false 有助于避免截断操作所需的表级ACCESS EXCLUSIVE锁。使用FULL选项时,此选项会被忽略。PARALLEL#指定可用于 Parallel Vacuum 的最大并行工作进程数,其数量还会进一步受到 max_parallel_maintenance_workers 的限制。此选项不能与
FULL选项一起使用。SKIP_DATABASE_STATS#指定
VACUUM应跳过更新数据库范围内关于最老未冻结 XID 的统计信息。通常,VACUUM会在命令结束时更新这些统计信息。不过,在拥有大量表的数据库中,这可能需要一段时间,而且只有当包含最老未冻结 XID 的表也在本次清理范围内时,这么做才有意义。此外,如果多个VACUUM命令并行发出,那么同一时间只能有一个命令更新数据库范围统计信息。因此,如果应用程序打算连续发出一系列VACUUM命令,那么除了最后一条命令之外,其余命令都可以设置此选项;或者在所有命令上都设置它,然后再单独执行VACUUM (ONLY_DATABASE_STATS)。ONLY_DATABASE_STATS#指定
VACUUM除了更新数据库范围内关于最老未冻结 XID 的统计信息外,不执行任何其他操作。指定该选项时,table_and_columns列表必须为空,并且除了VERBOSE之外不能启用其他任何选项。BUFFER_USAGE_LIMIT#指定
VACUUM所使用的缓冲区访问策略(Buffer Access Strategy)环形缓冲区大小。该大小用于计算在此策略中会被重用的共享缓冲区数量。0表示禁用缓冲区访问策略。如果同时指定了ANALYZE,那么BUFFER_USAGE_LIMIT的值会同时用于清理阶段和分析阶段。除非也指定了ANALYZE,否则该选项不能与FULL一起使用。如果未指定该选项,VACUUM会使用 vacuum_buffer_usage_limit 中的值。更高的设置可以让VACUUM运行得更快,但设置过大可能会把过多其他有用页面从共享缓冲区中逐出。最小值是128 kB,最大值是16 GB。FULL#该选项已弃用,它会使
VACUUM的行为类似于不带USING INDEX子句的REPACK。这种表压实方法比VACUUM耗时长得多,并且会独占锁定该表。这种方法还需要额外的磁盘空间,因为它会写出该表的一个新副本,并且在操作完成之前不会释放旧副本。通常,只有当需要从表内回收大量空间时才应使用这种方法。boolean#指定所选选项是否开启。可以写
TRUE、ON或1来启用选项,写FALSE、OFF或0来禁用它。也可以省略boolean值,此时假定为TRUE。integer#指定传递给所选选项的非负整数值。
size#指定以千字节为单位的内存大小。也可以把大小写成一个字符串,即数值后跟下列任一种内存单位:
B(字节)、kB(千字节)、MB(兆字节)、GB(吉字节)或TB(太字节)。table_name#要清理的特定表或物化视图的名称(可选地带模式限定)。如果在表名前指定
ONLY,则只清理该表。如果未指定ONLY,则还会清理该表及其所有继承子表或分区(如果有)。也可以在表名后显式指定*,以明确表示要清理继承子表(或分区)。column_name#要分析的特定列名。默认会分析所有列。如果指定了列列表,则也必须指定
ANALYZE。
输出
指定 VERBOSE 时,VACUUM 会输出进度消息,指示当前正在处理哪个表,同时还会打印这些表的各种统计信息。
注解
要清理一个表,通常必须拥有该表上的 MAINTAIN 权限。不过,数据库拥有者可以清理其数据库中的所有表,但共享系统目录除外。VACUUM 会跳过调用用户无权清理的任何表。
当 VACUUM 运行时,search_path 会被临时改为
pg_catalog, pg_temp。
VACUUM 不能在一个事务块内被执行。
对于带有 GIN 索引的表,VACUUM(任何形式)还会通过把待处理的索引项移动到主
GIN 索引结构中的适当位置,来完成所有挂起的索引插入。详见第 65.4.4.1 节。
我们建议定期对所有数据库执行清理,以移除死行。PostgreSQL 提供了一个“自动清理(autovacuum)”机制,可以自动执行常规清理维护。有关自动与手动清理的更多信息,参见第 24.1 节。
FULL 选项不建议在日常场景中使用,但在某些特殊情况下可能很有用。例如,当你删除或更新了表中的绝大多数行,并希望该表在物理上收缩以占用更少磁盘空间、让表扫描更快时,这个选项就比较合适。VACUUM FULL 通常会比普通
VACUUM 更大幅度地收缩表。
PARALLEL 选项只用于清理。如果此选项与 ANALYZE 选项一起指定,它不会影响 ANALYZE。
VACUUM 会显著增加 I/O 流量,这可能导致其他活动会话性能变差。因此,有时建议使用基于代价的清理延迟特性。对于并行清理,每个工作进程的睡眠时长都与该工作进程完成的工作量成比例。详见第 19.10.2 节。
每个运行不带 FULL 选项的 VACUUM 的后端,都会在
pg_stat_progress_vacuum 视图中报告其进度。运行 VACUUM FULL 的后端则会改为在
pg_stat_progress_cluster 视图中报告其进度。详见第 27.4.6 节和第 27.4.2 节。
示例
清理单个表 onek,对其进行分析以供优化器使用,并打印详细的清理活动报告:
VACUUM (VERBOSE, ANALYZE) onek;
兼容性
在 SQL 标准中没有 VACUUM 语句。
下列语法在 PostgreSQL 9.0 版本之前使用,并且目前仍受支持:
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ table_and_columns [, ...] ]
请注意,在这种语法中,选项必须严格按所示顺序指定。