
# VACUUM
在GaussDB中，当数据被更新或删除时，系统并不会立即释放物理空间，而是将其标记为"可重用"。随着时间推移，表中的死元组会越来越多。死元组（dead tuples）是指已被删除或因更新而被新版本覆盖，不再被任何活跃事务引用的历史数据行。
上述情况不仅会导致存储空间利用率下降，也可能影响查询性能，因为查询需要遍历这些无用的元组。而VACUUM命令的主要任务就是清理这些死元组，并回收相应的存储空间。
#### 为什么需要VACUUM
概括来说，VACUUM的核心目的就是清理持续累积的死元组、回收其占用的可重用空间，从而抑制Astore表膨胀、保障空间利用率与查询性能。
Astore存储引擎采用多版本并发控制（MVCC）来保证数据在高并发环境中的一致性和可访问性，每个事务在它开始的时间点都在其自己的数据库快照上运行，这就意味着无法立即删除过时的数据。当进行UPDATE和DELETE操作时，Astore存储引擎会为其他正在运行中的事务保留数据的历史版本：对于删除操作，并不会真正在数据页上删除元组，而是标记其被删除，这些被标记删除的元组即死元组；更新操作同样采用标记机制，相当于先标记删除原数据行，再插入新数据行。由于删除并非真正删除数据，死元组依旧占用磁盘空间，就会出现虽然查询表数据很少，但是表所占用磁盘空间很大的情况。此外，由于Astore的更新是基于追加写的，数据的新老版本在数据页面上共存，这进一步导致了数据库表空间的膨胀。
需要说明的是，Ustore存储引擎的日常旧版本回收由Undo子系统自治完成，不依赖VACUUM；但Ustore仍支持VACUUM与VACUUM FULL（如彻底回收物理空间），且系统表清理与空闲空间映射（FSM）维护仍依赖autovacuum。
#### VACUUM的优势是什么
- **控制表膨胀：**清理死元组并维护FSM，将过时数据占用的空间标记为可重用，供后续插入操作使用，避免表空间持续膨胀，提升空间复用能力。
- **轻量非阻塞：**普通VACUUM在清理过程中获取较低级别的锁，不阻塞业务的正常读写，对数据库性能影响较小，可在业务运行期间执行。
- **冻结旧事务：**在清理过程中尝试冻结旧事务，使元组对所有快照可见，从而在可见性判断、修改前检查等环节起到加速作用，便于推进表的冻结事务号（relfrozenxid）并回收CLOG/CSNLOG等事务文件。
- **支持自动清理：**通过autovacuum守护线程，数据库可在死元组达到阈值时自动触发清理与统计信息更新，减少人工运维负担。
 
#### VACUUM的使用场景
- **高频增删改表的膨胀治理：**对于订单、账务等存在大量UPDATE/DELETE的Astore业务表，运维团队常面临表占用空间远大于有效数据的膨胀问题。此时定期对表执行VACUUM，可清理死元组并将空间标记为可重用，从而控制表膨胀、维持稳定的查询性能，且执行期间不阻塞正常业务读写。
- **彻底回收磁盘空间：**当业务表已严重膨胀、需要将磁盘空间真正归还操作系统时，运维人员可在业务低谷期对表执行VACUUM FULL。该操作会重建原表并物理释放空间，但执行期间会锁表，期间无法对该表进行读写访问，因此适合在停业务窗口或低峰期对大表进行整理。
- **常态化自动维护：**在无需人工干预的常规运维中，DBA可开启autovacuum，由守护线程自动监测各表的死元组数量，在达到阈值时自动执行VACUUM与统计信息收集，使表膨胀和统计信息陈旧问题在日常运行中被持续抑制。
 
#### VACUUM的工作原理
VACUUM的执行可概括为"扫描清理、空间维护、事务冻结、信息更新"几个环节。系统首先扫描表中的页面，默认Lazy模式下会借助可见性映射（VM）跳过全可见页面，并将其中的死元组标记为可重用状态，但普通VACUUM并不重新组织活跃元组的物理存储位置，也不立即把空间归还操作系统，而是通过维护FSM记录可用空间，供后续插入复用。
在此基础上，VACUUM会尝试冻结旧事务，将元组事务标记为对所有快照可见，以加速可见性判断；同时更新VM、统计信息并回收事务文件等。普通VACUUM清理时获取较低级别的锁，不阻塞业务的正常读写。
自动清理由autovacuum守护线程实现，它由launcher与worker两类线程协同：autovacuum launcher在参数开启时常驻，负责调度；autovacuum worker实际连接数据库并对选定的表执行VACUUM。其触发依据死元组数量阈值，当死元组数超过autovacuum_vacuum_scale_factor × 表行数 + autovacuum_vacuum_threshold时即触发自动清理。通过手动VACUUM与autovacuum的配合，数据库得以在长期运行中持续回收空间、维护统计信息，保障性能稳定。
#### VACUUM的分类
按照清理力度和触发方式，VACUUM相关操作可分为以下几类：
1. 按清理力度，可分为普通VACUUM与VACUUM FULL。普通VACUUM仅标记并复用死元组空间、轻量非阻塞；VACUUM FULL重建表并将空间归还操作系统、需锁表，清理更彻底但代价更高。
   - **VACUUM**
     - **示例**
     
     
     ```
     --创建表tbl_test，并插入数据。
     gaussdb=# CREATE TABLE tbl_test(c1 int); 
     gaussdb=# INSERT INTO tbl_test VALUES (1); 
     --查看数据，和数据的ctid。
     gaussdb=# SELECT ctid,* FROM tbl_test;
      ctid  | c1 
     -------+----
      (0,1) |  1
     (1 row)
     --删除该数据。
     gaussdb=# DELETE FROM tbl_test;
     --重新插入一条数据，使用了一个新的ctid。
     gaussdb=# INSERT INTO tbl_test VALUES (2);
     gaussdb=# SELECT ctid,* FROM tbl_test;
      ctid  | c1 
     -------+----
      (0,2) |  2
     (1 row)
     --使用VACUUM命令回收之后，在插入数据，复用了旧的空间。
     gaussdb=# VACUUM ANALYZE tbl_test;
     gaussdb=# INSERT INTO tbl_test VALUES (3);
     gaussdb=# SELECT ctid,* FROM tbl_test;
      ctid  | c1 
     -------+----
      (0,1) |  3
      (0,2) |  2
     (2 rows)
     --删除表。
     gaussdb=# DROP TABLE tbl_test;
     ```
     
   
   - **VACUUM FULL**
     - 示例
     
     
     ```
     --建表。
     gaussdb=# CREATE TABLE tbl_test2(c1 int);
     --插入10万条数据并查看表的大小。
     gaussdb=# INSERT INTO tbl_test2 VALUES (generate_series(1,100000));
     gaussdb=# SELECT 'tbl_test2' AS tablename, pg_size_pretty(pg_relation_size('tbl_test2')) AS size;
      tablename |  size   
     -----------+---------
      tbl_test2 | 3048 kB
     (1 row)
     --删除数据并查看表大小。
     gaussdb=# DELETE FROM tbl_test2;
     gaussdb=# SELECT 'tbl_test2' AS tablename, pg_size_pretty(pg_relation_size('tbl_test2')) AS size;
      tablename |  size   
     -----------+---------
      tbl_test2 | 3048 kB
     (1 row)
     --使用VACUUM FULL回收空间,并查看表的大小。
     gaussdb=# VACUUM FULL ANALYZE tbl_test2;
     gaussdb=# SELECT 'tbl_test2' AS tablename, pg_size_pretty(pg_relation_size('tbl_test2')) AS size;
      tablename |  size   
     -----------+---------
      tbl_test2 | 0 bytes
     (1 row)
     ```
     
    
2. 按触发方式，可分为上文已介绍的手动VACUUM与自动清理（autovacuum）。手动VACUUM由用户主动执行，可控性强；autovacuum由守护线程根据死元组阈值自动触发，适合常态化维护。需要注意，业务DDL可终止autovacuum进程，但无法终止手动执行的VACUUM。
   - **自动清理（autovacuum）**
     表1autovacuum参数说明 
     | 参数名称                            | 默认值                                        | 参数解释                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
     |:---|:---|:---|
     | autovacuum                      | on                                         | 控制autovacuum是否打开。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
     | autovacuum_naption              | 600                                        | 控制两次autovacuum操作的时间间隔。默认值为600，表示600秒。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
     | autovacuum_mode                 | mix                                        | 控制autovacuum线程的具体操作： - analyze：表示只执行autoanalyze。  - vacuum：表示只执行autovacuum。  - mix：表示autoanalyze和autovacuum都执行。  - none：表示autoanalyze和autovacuum都不执行。   |
     | autovacuum_max_workers          | 3                                          | 同时运行autovacuum worker的最大线程数。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
     | autovacuum_vacuum_scale_factor  | 0.2                                        | 用于判断是否触发VACUUM。 取值范围：0.0\~100.0。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
     | autovacuum_vacuum_threshold     | 50                                         | 用于判断是否触发VACUUM。 取值范围：0\~2147483647。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
     | autovacuum_analyze_scale_factor | 0.1                                        | 用于判断是否触发ANALYZE。 取值范围：0.0\~100                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
     | autovacuum_analyze_threshold    | 50                                         | 用于判断是否触发ANALYZE。 取值范围：0\~2147483647                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
     | autovacuum_vacuum_cost_limit    | -1，表示该参数同vacuum_cost_limit（控制手动vacuum的参数）。 | autovacuum操作使用的开销值，即开销达到该值之前不会进入休眠。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
     | autovacuum_vacuum_cost_delay    | -1，表示该参数同vacuum_cost_delay（控制手动vacuum的参数）。 | autovacuum操作开销达到autovacuum_vacuum_cost_limit值之后休眠的时间。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
        
     
   
   
   当死元组数量达到阈值就会触发autovacuum，具体的阈值计算公式如下：
   ```
   number_of_dead_tuples > autovacuum_vacuum_scale_factor * reltuples + autovacuum_vacuum_threshold
   ```
   
3. 按作用对象，VACUUM相关操作可作用于普通表、系统表、Toast表、分区表、索引、压缩表（ILM）等多种对象。不同对象对VACUUM、AUTOVACUUM、VACUUM FULL三种操作的支持情况如下表所示。
   表2VACUUM对象类型 
   | 对象类型     | VACUUM | AUTOVACUUM | VACUUM FULL |
   |:---|:---|:---|:---|
   | 普通表      | √      | √          | √           |
   | 系统表      | √      | √          | √           |
   | Toast表   | √      | √          | √           |
   | EnToast表 | √      | √          | ×           |
   | 分区表      | √      | √          | √           |
   | 二级分区表    | √      | √          | √           |
   | 临时表      | √      | ×          | √           |
   | 全局临时表    | √      | ×          | √           |
   | 索引       | √      | √          | ×           |
   | 压缩表（ILM） | √      | √          | √           |
      
   
 
#### VACUUM与VACUUM FULL的区别
VACUUM与VACUUM FULL都是GaussDB中用于清理表空间、处理死元组的命令，二者的共同点在于都用于回收过时数据占用的空间、缓解表膨胀。
二者的核心差异在于清理方式与对业务的影响：普通VACUUM只将死元组空间标记为可重用，并不进行物理删除，也不把空间归还操作系统，过程中仅获取4级锁（ShareUpdateExclusiveLock），不影响读写；VACUUM FULL则会重建原表、物理删除死元组并将空间释放给操作系统，但执行期间会获取8级锁（AccessExclusiveLock），阻塞其他事务的读写访问。
这一差异决定了二者的适用场景不同：VACUUM是轻量级、不阻塞业务的常规清理手段，适合日常频繁执行；VACUUM FULL是重量级操作，执行时间随数据量增长，适合在业务低谷期对严重膨胀的表做彻底空间回收。
| **对比维度** | **VACUUM**                             | **VACUUM FULL**                  |
|:---|:---|:---|
| 共同点      | 均用于清理死元组、缓解表膨胀。                                                          ||
| 清理方式     | 标记死元组空间为可重用，不物理删除。                     | 重建原表，物理删除死元组。                    |
| 空间归还     | 仅供库内复用，不归还操作系统。                        | 将空间释放给操作系统。                      |
| 是否锁表     | 获取4级锁（ShareUpdateExclusiveLock），不影响读写。 | 获取8级锁（AccessExclusiveLock），影响读写。 |
| 性能影响     | 轻量级，影响小。                               | 重量级，影响大。                         |
| 适用场景     | 日常常规清理。                                | 业务低谷期彻底回收空间。                     |
   
#### Astore VACUUM与Ustore VACUUM的区别
本节对比GaussDB新一代存储引擎Ustore与Astore在VACUUM机制和功能上的差异。Astore的堆表与Btree索引、Ustore的堆表与UB-tree索引（分为RCR与PCR两种格式）在AUTOVACUUM、VACUUM、VACUUM FULL三种操作下的功能支持情况如下三张表所示。
表3表3 AUTOVACUUM功能对比 
| AUTOVACUUM  | Astore | Btree | Ustore | Ubtree（RCR） | Ubtree（PCR） |
|:---|:---|:---|:---|:---|:---|
| 扫描并删除行的无效版本 | √      | √     | ×      | √           | √           |
| 维护统计信息      | √      | √     | ×      | ×           | ×           |
| 维护FSM准确性    | √      | √     | √      | √           | √           |
| 维护VM准确性     | √      | ×     | ×      | ×           | ×           |
| 冻结过老的事务号    | √      | ×     | ×      | √           | ×           |
| 回收事务文件      | √      | √     | √      | √           | √           |
| 释放物理空间      | ×      | ×     | ×      | ×           | ×           |
   
表4表4 VACUUM功能对比 
| VACUUM      | Astore | Btree | Ustore | Ubtree（RCR） | Ubtree（PCR） |
|:---|:---|:---|:---|:---|:---|
| 扫描并删除行的无效版本 | √      | √     | √      | √           | √           |
| 维护统计信息      | √      | √     | √      | √           | √           |
| 维护FSM准确性    | √      | √     | √      | √           | √           |
| 维护VM准确性     | √      | ×     | ×      | ×           | ×           |
| 冻结过老的事务号    | √      | ×     | √      | √           | √           |
| 回收事务文件      | √      | √     | √      | √           | √           |
| 释放物理空间      | ×      | ×     | ×      | ×           | ×           |
   
表5表5 VACUUM FULL功能对比 
| VACUUM FULL | Astore | Btree | Ustore | Ubtree（RCR） | Ubtree（PCR） |
|:---|:---|:---|:---|:---|:---|
| 释放物理存储空间    | √      | √     | √      | √           | √           |
   
#### 与VACUUM相关的特性和操作
在了解VACUUM的核心概念与分类后，如需了解更多细节以及在实际业务中配置使用，可参考以下对应章节：
- 对表执行VACUUM：对指定表执行清理操作以回收空间，详情参考《管理员指南》中"导入数据 \> 对表执行VACUUM"章节。
- VACUUM语法：了解VACUUM/VACUUM FULL命令的完整语法与参数，详情参考《参考》中"SQL参考 \> SQL语法 \> V \> VACUUM"章节。
- 自动清理与参数配置：通过autovacuum、autovacuum_vacuum_scale_factor、autovacuum_vacuum_threshold等参数控制自动清理的开启与触发条件，详情参考《参考》中"数据库运行参数说明 \> GUC参数说明 \> 自动清理"章节及《性能调优》中"VACUUM/autovacuum介绍与调优 \> autovacuum的相关参数"章节。
- VACUUM/autovacuum调优：针对清理效率与膨胀控制进行优化，详情参考《性能调优》中"VACUUM/autovacuum介绍与调优"章节。
 
