
vacuum的功能
回收空间
数据库总是不断地在执行删除,更新等操作。良好的空间管理非常重要,能够对性能带来大幅提高。
执行delete操作后,表中的记录只是被标示为删除状态,并没有释放空间,在以后的update或insert操作中该部分的空间是不能够被重用的。
在数据库中用于维护数据库磁盘空间的工具是VACUUM,其重要的作用是删除那些已经标示为删除的数据并释放空间。经过vacuum清理后,空间才能得到释放。
VACUUM回收已删除元组占据的存储空间。在一般的数据库操作里,那些已经DELETE的元组或者被UPDATE过后过时的元组是没有从它们所属的表中物理删除的;在完成VACUUM之前它们仍然存在。因此我们有必须周期地运行VACUUM,特别是在常更新的表上。
冻结tuple的xid
在每条记录(tuple)的header中,存放xmin,xmax信息(增删改事务ID)。transactionID的最大值为2的32次,即无符整形来表示。当transactionID超过此最大值后,会循环使用。
这会带来一个问题:就是最新事务的transactionID会小于老事务的transactionID。如果这种情况发生后,就没有办法按transactionID来区分事务的先后,也没有办法实现MVCC了。
因此用vacuum后台进程,按一定的周期和算法触发vacuum动作,将过老的tuple的header中的事务ID进行冻结。冻结事务ID,即将事务ID设置为“2”(“0”表示无效事务ID;“1”表示bootstrap,即初始化;“3”表示最小的事务ID)。被冻结的事务ID比任何事务都要老。这样就不会出现上面的这种情况了。
更新visibility map
在数据库中,有一个visibility map用来标记那些page中是没有dead tuple的。这有两个好处,一是当vacuum进行scan时,直接可以跳过这些page。二是进行index-only scan时,可以先检查下visibility map。这样减少fetch tuple时的可见性判断,从而减少IO操作,提高性能。另外visibility map相对整个relation,还是小很多,可以cache到内存中。
vacuum full与vacuum的区别
vacuum full的执行流程
建临时表
拷贝数据
表交换
新表将老表替换掉。会对pg_class再次申请“RowExclusiveLock”锁。
重建索引
是在交换之后完成的,重建索引时,会更新一些统计信息。对表申请“ShareLock”锁。
删除临时表
索引重建完成后,将带有老物理文件的新临时表进行删除。
vacuum full执行慢的常见场景
1. 存在锁争抢
查看该线程的等待状态,如果等待状态是acquire lock,说明存在锁等待
在pg_locks中查询vacuum full在等哪个锁

根据语句判断是否可以杀掉该语句继续做vacuum full,或者另外找时间窗做vacuum full。
2. 存在IO/网络问题导致事务无法提交
执行一个简单的create table语句,如果create table语句执行也很慢,说明存在IO/网络问题,进一步排查IO和网络。
3. 系统表过大导致vacuum full慢
vacuum full任意一张表时,都会扫描pg_class、pg_partition、pg_proc三张系统表,当这三个系统表过大时,也会导致vacuum full较慢。
可以在排除IO/网络问题(即create table语句不慢)后,对空表做vacuum full,观察执行速度,如果空表做vacuum full也比较慢,则说明就是这三张系统表较大导致vacuum full任意表都慢。
4. 排除以上场景之后,可以查看表定义中是否使用了PCK
当存在PCK时,表做vacuum full时会进行全排序,此时如果表较大或psort_work_mem设置较小,就会导致PCK排序时产生下盘,进行外排,效率急剧下降。
可以通过调大psort_work_mem进行规避。
【推荐阅读】
华为GaussDB(DWS)数据仓库,助力招行“人人用数,创新前行” 华为云GaussDB(DWS)数据仓库以2048大规模节点通过信通院评测认证 五大关键能力,华为云原生数据仓库GaussDB(DWS)深度技术解读 GaussDB(DWS)delete误删数据后如何恢复? Unique SQL特性原理与应用 






