摘要:在数据库中用于保护数据库磁盘空间的工具是VACUUM,其重要的作用是删除那些曾经标示为删除的数据并开释空间。

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的区别

1.vacuum只是将删除状态的空间开释掉,转换到可能从新应用的状态,然而对于零碎来说该数据块的闲暇空间并没有反馈到零碎的元数据中,并不进行空间合并。

而vacuum full本质上是重建了整个表,以达到空间合并的成果。

2.vacuum执行过程中对表加4级锁,不会影响表的增删改查,而vacuum full对表加8级锁,执行过程中表无法访问。

3.vacuum对列存表有效

vacuum full的执行流程

建长期表

数据库会新建一个长期表,长期表继承老表所有属性。

这个阶段会对pg_class申请“RowExclusiveLock”锁,因为须要插入记录。

拷贝数据

将原来的数据copy到temp表中。

对长期表,老表以及索引都以“AccessExclusiveLock”模式关上。

另外对于toast,只是lock,不关上。

在这个过程中实现Dead Tuple的清理。

表替换

新表将老表替换掉。会对pg_class再次申请“RowExclusiveLock”锁。

重建索引

是在替换之后实现的,重建索引时,会更新一些统计信息。对表申请“ShareLock”锁。

删除长期表

索引重建实现后,将带有老物理文件的新长期表进行删除。

vacuum full执行慢的常见场景

1. 存在锁争抢

在cn上执行select * from pg_stat_activity where query like '%vacuum%';找到vacuum full的pid

查看该线程的期待状态,如果期待状态是acquire lock,阐明存在锁期待

select * from pg_thread_wait_status where tid = 139878309295872;

在pg_locks中查问vacuum full在等哪个锁

select * from pg_locks where pid = 139878309295872 and granted = 'f';

查看持有该锁的线程

select * from pg_locks where relation = 544793 and granted = 't';

查看该线程对应的语句

select query from pg_stat_activity where pid = 139877539612416;

依据语句判断是否能够杀掉该语句持续做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进行躲避

点击关注,第一工夫理解华为云陈腐技术~