vacuum的功能
回收空间
数据库总是不断地在执行删除,更新等操作。良好的空间管理非常重要,能够对性能带来大幅提高。
postgresql中执行delete操作后,表中的记录只是被标示为删除状态,并没有释放空间,在以后的update或insert操作中该部分的空间是不能够被重用的。
在postgresql中用于维护数据库磁盘空间的工具是VACUUM,其重要的作用是删除那些已经标示为删除的数据并释放空间。经过vacuum清理后,空间才能得到释放。
VACUUM回收已删除元组占据的存储空间。在一般的PostgreSQL操作里,那些已经DELETE的元组或者被UPDATE过后过时的元组是没有从它们所属的表中物理删除的;在完成VACUUM之前它们仍然存在。因此我们有必须周期地运行VACUUM,特别是在常更新的表上。
冻结tuple的xid
PG会在每条记录(tuple)的header中,存放xmin,xmax信息(增删改事务ID)。transactionID的最大值为2的32次,即无符整形来表示。当transactionID超过此最大值后,会循环使用。
这会带来一个问题:就是最新事务的transactionID会小于老事务的transactionID。如果这种情况发生后,PG就没有办法按transactionID来区分事务的先后,也没有办法实现MVCC了。
因此PG用vacuum后台进程,按一定的周期和算法触发vacuum动作,将过老的tuple的header中的事务ID进行冻结。冻结事务ID,即将事务ID设置为“2”(“0”表示无效事务ID;“1”表示bootstrap,即初始化;“3”表示最小的事务ID)。PG认为被冻结的事务ID比任何事务都要老。这样就不会出现上面的这种情况了。
更新统计信息
vacuum analyze时,会更新统计信息,让PG的planner能够算出更准确的执行计划。autovacuumanalyzethreshold和autovacuum_analyzescalefactor参数可以控制analyze的触发的频率。
更新visibility map
在PG中,有一个visibility map用来标记那些page中是没有dead tuple的。这有两个好处,一是当vacuum进行scan时,直接可以跳过这些page。二是进行index-only scan时,可以先检查下visibility map。这样减少fetch tuple时的可见性判断,从而减少IO操作,提高性能。另外visibility map相对整个relation,还是小很多,可以cache到内存中。
执行语法
sql语句
VACUUM语法结构
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ table ]
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
系统命令
vacuumdb --help
Full Vacuum
full vacuum与单纯的vacuum的区别
vacuum只是将删除状态的空间释放掉,转换到能够重新使用的状态,但是对于系统来说该数据块的空闲空间并没有反应到系统的元数据中,并不进行空间合并。
vacuum full除了vacuum,还进行空间合并,会锁表和索引,而且是“AccessExclusiveLock”级别的,其实vacuum full会重建整个表。
vacuum full将会使空间释放的信息表现在系统级别,其实质是将当前删除记录后面的数据进行移动,使得整体的记录连贯起来。
vacuum full的执行流程
建临时表
PG会新建一个临时表,临时表继承老表所有属性。
这个阶段会对pg_class申请“RowExclusiveLock”锁,因为需要插入条目。
拷贝数据
将原来的数据copy到temp表中。
对临时表,老表以及索引都以“AccessExclusiveLock”模式打开。
另外对于toast,只是lock,不打开。
在这个过程中完成Dead Tuple的清理。
表交换
新表将老表替换掉。会对pg_class再次申请“RowExclusiveLock”锁。
重建索引
是在交换之后完成的,重建索引时,会更新一些统计信息。对表申请“ShareLock”锁。
删除临时表
索引重建完成后,将带有老物理文件的新临时表进行删除。
注意
执行过程中锁表,大部分时间无法访问,对业务影响很大
执行过程消耗时间长,消耗大量IO、内存、CPU等
对于大表和业务繁忙时间最后不要执行
一般合理设置vacuum参数,进行常规vacuum也就够了。
Vacuum analyze
analyze的功能是更新统计信息,使得优化器能够选择更好的方案执行sql。
统计信息收集和更新对于系统性能来说非常重要,与oracle维护类似,通常可以通过采用手动或者定制任务的方式。也有不同,oracle在进行imp后自动的对相应数据对象进行统计信息的收集和更新,而postgresql的恢复过程还没有集成到里面,需要手动去执行。
autovacuum
autovacuum定时自动进行vacuum。
对于有大量update的表,vacuum full是没有必要的,因为它的空间还会再次增长,所以vacuum就足够了。
参数
autovacuum:默认为on,表示是否开起autovacuum。
默认开起。特别的,当需要冻结xid时,尽管此值为off,PG也会进行vacuum。
autovacuum_naptime:检查执行vacuum的间隔,默认1min。
该值会被vacuum launcher分配到每个DB上。autovacuum_naptime/num of db。
log_autovacuum_min_duration:当vacuum动作执行超时,记录日志。
-1关闭vacuum的日志记录,0表示所有log。正整数表示超时时间。
autovacuum_max_workers:最大同时运行的worker数,不包含launcher本身。
默认值为3。配置主要依据系统当前负载和资源。
对于系统负载较重的情况,建议开启少量的进程为好,反之,空闲时间可以采用较大值的方式。