
# DWS表膨胀原因有哪些？该如何处理？
#### 表膨胀的原因
- 未开启autovacuum DWS提供自动执行VACUUM和ANALYZE命令的系统自动清理进程（autovacuum），用于回收被标识为删除状态的记录空间，并更新表的统计数据。
  用户未开启autovacuum的同时又没有合理的自定义vacuum调度，导致表的脏数据没有及时回收，新的数据又不断插入或更新，膨胀是必然的。
  
- 资源回收不及时 开启了autovacuum，但是各种原因导致回收不及时，并且新的数据又不断产生，从而导致膨胀。回收不及时有以下原因：
  - IO性能差 当数据库非常繁忙时，如果IO性能较差，会导致回收脏数据变慢，从而导致表膨胀。
    这种情况一般出现在占用数据库内存较大的表上，并且这些表正在执行整表vacuum，因此产生大量IO，导致表自身或其他表膨胀。
    
  
  - autovacuum触发较迟 触发autovacuum操作的阈值设置过高，大量表上被删除、插入或更新的记录数没有及时处理，导致表膨胀。
    
  
  - autovacuum线程繁忙 所有自动清理线程繁忙，某些表产生的脏数据超过阈值，但是在此期间没有autovacuum线程可以处理脏数据回收的事情，可能发生表膨胀。
    如果数据库的表很多，而且都比较大，那么当需要vacuum的表超过了配置autovacuum_max_workers的数量，这些表就要等待空闲的autovacuum线程。这个阶段就容易出现表的膨胀。
    
  
  - 数据库中存在长SQL或带XID的长事务 当DWS数据库中存在未结束的SQL语句或者未结束的持有事务ID的事务，在此SQL执行时间范围内或在此事务过程中产生的脏数据无法回收，导致数据库膨胀。
    
  
  - 开启了autovacuum_vacuum_cost_delay 在开启了autovacuum_vacuum_cost_delay后，会使用基于成本的脏数据回收策略，可以有利于降低VACUUM带来的IO影响，但是对于IO性能高的系统，开启autovacuum_vacuum_cost_delay反而会使得垃圾回收的时间变长。
    
  
  - autovacuum_naptime设置间隔时间过长
  
  - 批量删除或更新大表 例如对于一个10GB的表，一条SQL或一个事务中删除或更新9GB的数据，这9GB的数据必须在事务结束后才能进行脏数据回收，无形中增加了膨胀的可能。
    
   
 
#### 减少或避免表膨胀
- 开启autovacuum。
- 提高系统的IO能力。
- 调整触发阈值，让触发阈值和记录数匹配。
- 增加autovacuum_max_workers和autovacuum_work_mem，同时增加系统内存。
- IO性能较好的系统，关闭autovacuum_vacuum_cost_delay。
- 设计应用程序时，避免使用大批量的更新、删除操作，可以切分为多个事务进行。
- 应用程序设计时，尽量避免下列操作：
  - 打开游标后不关闭。
  
  - 在不必要的场景使用repeatable read或serializable事务隔离级别。
  
  - 对大的数据库执行gs_dump进行逻辑备份（隐式repeatable read隔离级别的全库备份）。
  
  - 长时间不关闭申请了事务号的事务（增、删、改等DDL操作的SQL）。
   
 
#### 相关空间回收参数说明
- autovacuum = on 控制数据库自动清理进程（autovacuum）的启动。自动清理进程运行的前提是将track_counts设置为on。
  

- log_autovacuum_min_duration = 0 当自动清理的执行时间大于或者等于某个特定的值时，向服务器日志中记录自动清理执行的每一步操作。设置此选项有助于追踪自动清理的行为。
  

- autovacuum_max_workers = 10 设置能同时运行的自动清理线程的最大数量。
  

- autovacuum_naptime = 1 设置两次自动清理操作的时间间隔。
  

- autovacuum_vacuum_cost_delay = 0 设置在自动VACUUM操作里使用的开销延迟数值。
  
更多关于空间回收参数说明，参见[自动清理](https://support.huaweicloud.com/devg-dws/dws_04_0923.html)。
