摘要:在数据库中用于维护数据库磁盘空间的工具是VACUUM,其重要的做用是删除那些已经标示为删除的数据并释放空间。
vacuum的功能
回收空间
数据库老是不断地在执行删除,更新等操做。良好的空间管理很是重要,可以对性能带来大幅提升。算法
执行delete操做后,表中的记录只是被标示为删除状态,并无释放空间,在之后的update或insert操做中该部分的空间是不可以被重用的。数据库
在数据库中用于维护数据库磁盘空间的工具是VACUUM,其重要的做用是删除那些已经标示为删除的数据并释放空间。通过vacuum清理后,空间才能获得释放。bootstrap
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比任何事务都要老。这样就不会出现上面的这种状况了。fetch
更新visibility map
在数据库中,有一个visibility map用来标记那些page中是没有dead tuple的。这有两个好处,一是当vacuum进行scan时,直接能够跳过这些page。二是进行index-only scan时,能够先检查下visibility map。这样减小fetch tuple时的可见性判断,从而减小IO操做,提升性能。另外visibility map相对整个relation,仍是小不少,能够cache到内存中。ui
vacuum full与vacuum的区别
1.vacuum只是将删除状态的空间释放掉,转换到可以从新使用的状态,可是对于系统来讲该数据块的空闲空间并无反应到系统的元数据中,并不进行空间合并。spa
而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进行规避