VACUUM
功能描述
VACUUM回收表或B-Tree索引中已经删除的行所占据的存储空间。在一般的数据库操作里,那些已经DELETE的行并没有从它们所属的表中物理删除;在完成VACUUM之前它们仍然存在。因此有必要周期地运行VACUUM,特别是在经常更新的表上。
注意事项
- 如果没有参数,VACUUM处理当前数据库里用户拥有相应权限的每个表。如果参数指定了一个表,VACUUM只处理指定的那个表。
- 要对一个表进行VACUUM操作,通常用户必须是表的所有者,被授予了指定表VACUUM权限的用户或者被授予了gs_role_vacuum_any角色的用户,系统管理员默认拥有此权限。数据库的所有者允许对数据库中除了共享目录以外的所有表进行VACUUM操作(该限制意味着只有系统管理员才能真正对一个数据库进行VACUUM操作)。VACUUM命令会跳过那些用户没有权限的表进行垃圾回收操作。
- VACUUM不能在事务块内执行。
- 建议生产数据库经常清理(至少每晚一次),以保证不断地删除失效的行。尤其是在增删了大量记录之后,对受影响的表执行VACUUM ANALYZE命令是一个很好的习惯。这样将更新系统目录为最近的更改,并且允许查询优化器在规划用户查询时有更好的选择。
- 不建议日常使用FULL选项,但是可以在特殊情况下使用。例如在用户删除了一个表的大部分行之后,希望从物理上缩小该表以减少磁盘空间占用。VACUUM FULL通常要比单纯的VACUUM收缩更多的表尺寸。如果执行此命令后所占用物理空间无变化(未减少),请确认是否有其他活跃事务(删除数据事务开始之前开始的事务,并在VACUUM FULL执行前未结束)存在,如果有等其他活跃事务退出进行重试。
- VACUUM会导致I/O流量的大幅增加,这可能会影响其他活动会话的性能。因此,有时候会建议使用基于开销的VACUUM延迟特性。
- 如果指定了VERBOSE选项,VACUUM将打印处理过程中的信息,以表明当前正在处理的表。各种有关当前表的统计信息也会打印出来。
- 语法格式中含有带括号的选项列表时,选项可以以任何顺序写入。如果没有括号,则选项必须按语法显示的顺序给出。
- VACUUM和VACUUM FULL时,会根据参数vacuum_defer_cleanup_age延迟清理行存表记录,即不会立即清理刚删除的元组。
- VACUUM ANALYZE先执行一个VACUUM操作,然后给每个选定的表执行一个ANALYZE。对于日常维护脚本而言,这是一个很方便的组合。
- 简单的VACUUM(不带FULL选项)只是简单地回收空间并且令其可以再次使用。这种形式的命令可以和对表的普通读写并发操作,因为没有请求排他锁。VACUUM FULL执行更广泛的处理,包括跨块移动行,以便把表压缩到最少的磁盘块数目里。这种形式要慢许多并且在处理的时候需要在表上施加一个排他锁。
- VACUUM列存表内部执行的操作包括四个:VACUUM主表、VACUUM主表的desc表、VACUUM主表的delta表、迁移delta表中的数据到主表。该操作不会回收delta表的存储空间,如果要回收delta表的冗余存储空间,需要对该列存表执行VACUUM DELTAMERGE。VACUUM主表操作默认开启,可以通过调节参数colvacuum_threshold_scale_factor来关闭该功能。
- VACCUM列存主表功能不支持临时表、冷热表和时序表。
- VACUUM列存主表功能对空间的回收是延后的,若需要立即回收空间,在执行VACUUM后,运行vac_fileclear_relation函数,将会对指定表施加排他锁,完成空间回收。
- VACUUM FULL系统表只能离线操作,在线VACUUM FULL系统表除了会锁表,还可能导致一些异常情况并产生报错。
- 如果有长查询访问系统表,此时执行VACUUM FULL,长查询可能会阻塞VACUUM FULL连接访问系统表,导致连接超时报错。
- 对列存分区表执行VACUUM FULL,会同时锁表和锁分区。
- VACUUM FULL操作分区表时与用户DML语句在如下特定场景有并发时可能发生分布式死锁,请谨慎操作:
- VACUUM FULL子分区与insert/update/delete主表。
- VACUUM FULL全表与select全表/select子分区。
- 对表执行VACUUM FULL操作时会触发表重建(表重建过程中会先把数据转储到一个新的数据文件中,重建完成之后会删除原始文件),当表比较大时,重建会消耗较多的磁盘空间。当磁盘空间不足时,要谨慎对待大表VACUUM FULL操作,防止触发集群只读。
- 在存算分离架构下,对于全库VACCUM/全库VACUUM FULL/全库VACUUM DELTAMERGE提示不支持。
语法格式
- 回收空间并更新统计信息,关键字顺序必须按语法显示的顺序给出。
1 2
VACUUM [ ( { FULL | FREEZE | VERBOSE | {ANALYZE | ANALYSE }} [,...] ) ] [ table_name [ (column_name [, ...] ) ] ] [ PARTITION ( partition_name ) ];
- 仅回收空间,不更新统计信息。
1
VACUUM [ FULL [COMPACT] ] [ FREEZE ] [ VERBOSE ] [ table_name ] [ PARTITION ( partition_name ) ];
- 回收空间并更新统计信息,且对关键字顺序有要求。
1 2
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] { ANALYZE | ANALYSE } [ VERBOSE ] [ table_name [ (column_name [, ...] ) ] ] [ PARTITION ( partition_name ) ];
- 针对HDFS表和列存表,将delta table中的数据转移到主表存储。(partition_name参数仅8.2.1.300及以上集群版本支持)
1
VACUUM DELTAMERGE [ table_name ][partition_name];
- 针对HDFS表,删除HDFS表在HDFS存储上的空值分区目录。
1
VACUUM HDFSDIRECTORY [ table_name ];
参数说明
- FULL
选择“FULL”清理,这样可以恢复更多的空间,但是需要耗时更多,并且在表上施加了排他锁。
FULL选项还可以带有COMPACT参数,该参数只针对HDFS表,指定该参数的VACUUM FULL操作性能要好于未指定该参数的VACUUM FULL操作。
COMPACT和PARTITION参数不能同时使用。
使用FULL参数会导致统计信息丢失,如果需要收集统计信息,请在VACUUM FULL语句中加上analyze关键字。
- FREEZE
指定FREEZE相当于执行VACUUM时将vacuum_freeze_min_age参数设为0。
- VERBOSE
为每个表打印一份详细的清理工作报告。
- ANALYZE | ANALYSE
更新用于优化器的统计信息,以决定执行查询的最有效方法。
- table_name
要清理的表的名称(可以有模式修饰)。
取值范围:要清理的表的名称。缺省时为当前数据库中的所有表。
- column_name
要分析的具体的字段名称。
取值范围:要分析的具体的字段名称。缺省时为所有字段。
- PARTITION
HDFS表不支持PARTITION参数,PARTITION参数不能和COMPACT同时使用。
PARTITION参数和COMPACT同时使用会报错:COMPACT can not be used with PARTITION.
- partition_name
要清理的表的分区名称。缺省时为所有分区。
- DELTAMERGE
只针对HDFS表和列存表,将HDFS表或者列存表的delta table中的数据转移到主表存储上。对HDFS表而言,当delta表中数据量小于六万行,则不作迁移,只有在大于或者等于六万行数据时,将delta表中所有数据迁移到HDFS上,并通过truncate清理delta表的存储空间。对列存表而言,此操作总是会将delta表中的数据全部转移到CU中。
为了检查列存delta表中的信息(HDFS表的delta表数据可以通过explain analyze查到),提供下述DFX函数,用于获取某个列存表的delta表中数据存储情况:
- pgxc_get_delta_info(TEXT),传入参数为列存表名,搜集并显示各个节点上的对应delta表信息,包括当前存活tuple数量、表大小、使用的最大block ID。
- get_delta_info(TEXT),传入参数为列存表名,汇总pgxc_get_delta_info得到的结果,返回其delta表整体的当前存活tuple数量、表大小、使用的最大block ID。查询临时表delta信息时,需要显示指定临时表的schema,否则会报错找不到表。
- HDFSDIRECTORY
只针对HDFS表,删除HDFS表在HDFS存储上表目录下的空值分区目录。
示例
清理当前数据库中的所有表:
1
|
VACUUM; |
仅回收表tpcds.web_returns_p1分区P2的空间,不更新统计信息:
1
|
VACUUM FULL tpcds.web_returns_p1 PARTITION(P2); |
回收表tpcds.web_returns_p1空间,并更新统计信息:
1
|
VACUUM FULL ANALYZE tpcds.web_returns_p1; |
清理当前数据库中的所有表并收集查询优化器的统计信息:
1
|
VACUUM ANALYZE; |
仅清理特定表reason:
1
|
VACUUM (VERBOSE, ANALYZE) tpcds.reason; |
对列存表table_delta进行DELTAMERGE操作:
1
|
VACUUM DELTAMERGE tpcds.table_delta; |
仅对列存表table_delta的分区p1进行DELTAMERGE操作:
1
|
VACUUM DELTAMERGE tpcds.table_delta partition(p1); |