PostgreSQL清理dead tuples(vacuum和vacuum full)

前言

PostgreSQL的并发控制,采用MVCC(多版本并发控制)进行处理。这种机制有一个缺点:随着时间的推移,数据文件中积累的dead tuples(死数据/死元组)会越来越多。

在清理dead tuples时,系统有两种处理方式:vacuum 和 vacuum full。

简单使用

vacuum 表名;
vacuum full 表名;

vacuum和vacuum full区别

Vacuum Full和Vacuum最大的不同就是:Vacuum Full是物理删除dead tuples,并把释放的空间重新交给操作系统,所以在vacuum full后,表的大小会减小为实际的空间大小。

  • vacuum:只是把表中的dead tuples进行删除标记,并没有真正物理删除;将dead tuple的行的空间转换为能够使用的状态,vacuum过程中,可以正常访问数据表,不锁表。
  • vacuum full:物理删除表中的dead tuples,释放空间给操作系统;vacuum full过程中,表被锁定,不允许访问。
    在这里插入图片描述

原理

Vacuum过程

  1. 清除dead tuples指向的index tuples

vacuum会顺序扫描目标表,并构建一个dead tuples组成的list链表,该list链表会存储在maintenance_work_mem缓存中。然后vacuum根据dead tuples list移除dead tuples指向的index索引。

  1. 移除dead tuples,更新VM(可见性映射文件)和FSM(空闲空间映射文件)

这里的移除dead tuples只是标记为可重用该空间,并没有真正物理删除。所以vacuum清理表后,表的实际空间并没有减小。dead tuples在做移除标记后,vacuum会重新排列剩余的元组以进行碎片化整理。然后,需要更新目标表的VM(可见性映射文件)和FSM(空闲空间映射文件)。

  1. 更新统计信息和相关系统表

更新vacuum目标表的统计信息(以适应最新的查询优化)和相关系统表。

AutoVacuum守护进程
  • 由于vacuum是数据库系统的一个例行性维护,所以系统启动后,会开启一个AutoVacuum守护进程专门对此处理
  • AutoVacuum清理进程一般用vacuum而避免使用vacuum full。
    理由:vacuum尽管可以保持表的最小尺寸,但是如果表还有继续增长的空间,这么做就意义不大了,特别是对于频繁写入的表。而且vacuum在执行效率上也比vacuum full好。
  • AutoVacuum进程是一个launcher进程,它不进行vacuum操作,它负责启动vacuum worker进程,然后由vacuum worker进程进行相应的vacuum和analyze操作
    在这里插入图片描述

AutoVacuum进程会在每autovacuum_naptime时间间隔内为数据库启动autovacuum worker进程。然后每个worker进程会检查数据库中的每一个表,在需要时执行vacuum或analyze操作。如果有N个数据库,则每 autovacuum_naptime/N秒将启动一个新worker进程,在同一时间只允许最多autovacuum_max_workers 个worker进程运行,如果有超过autovacuum_max_workers 个数据库需要被处理,下一个数据库将在第一个worker结束后马上被处理。

Vacuum Full过程

  1. vacuum full开始执行时,系统会先对目标创建一个AccessExclusiveLock(访问独占锁/读排它锁),不允许外界再进行访问(为后面拷贝做准备),然后创建一个表结构和目标表相同的新表。
  2. 扫描目标表,把表中的live tuples(活数据/活元组)拷贝到新表中。
  3. 删除目标表,在新表上,重新创建索引,更新VM(可见性映射文件), FSM(空闲空间映射文件)以及统计信息,相关系统表等。

猜你喜欢

转载自blog.csdn.net/qq_37432174/article/details/131039095