暂无图片
暂无图片
4
暂无图片
暂无图片
暂无图片

pg表膨胀处理

原创 进击的CJR 2022-05-15
3110

表膨胀

是指表的数据和索引所占文件系统的空间,在有效数据量并未发生大的变化的情况下,不断增大。久而久之,关系文件被大量空洞填满,浪费了大量的磁盘空间。甚至某些特殊场景下,一个表中只有一条简单的数据,但是表对应的物理文件可能已经达到M级甚至G级。


为什么会表膨胀

Postgresql通过数据多版本实现mvcc,删除数据并不会真正删除数据,而是修改标识,更新是通过删除+插入的方式进行,所以在频繁更新的系统,如果不进行处理,数据膨胀倍数可能达到十几倍。


表膨胀危害

空间持续上涨,到达某一个点后,需要执行一个高额代价的vacuum full(或者cluster等可以重组表的命令),但vacuum full又是AccessExclusiveLock,8级锁,会阻塞一切访问,意味着在完成清理重组之前,都无法访问该表。
扫描的效率变低,即使所有记录都是dead状态,PostgreSQL的顺序扫描也会扫描对象所有的老版本,直到执行vacuum将dead的记录删除。


处理表膨胀

为了处理膨胀问题,pg提供了vacuum工具,vacuum分为普通vacuum和vacuum full,普通vacuum会清理死元组,但是不会进行空间重组,磁盘上的空间不会释放,但是会释放死元组的空间,后续插入的元组会根据空闲空间管理fsm优先插入空闲空间。Vacuum full清理会释放磁盘空间,但是会获取八级锁,因为vacuum full的原理是新建一个表数据文件,然后从老表中拷贝数据到新文件中,这个过程会阻塞select。

处理工具,pg_repack pgcompacttable
能够突破vacuum full的限制,在不阻止表的访问的情况下完成vacuum full的功能。


pg_repack

创建一个新表,将数据从旧表移动到新表。为了避免表被独占锁定,创建了一个额外的日志表来记录原始表的改动,还添加了一个把INSERT / UPDATE / DELETE操作记录到日志表的触发器。当原始表中的数据全部导入到新表中,索引重建完毕,日志表的改动全部完成,pg_repack会连同新索引,用新表替换旧表,并将原旧表Drop掉。整个过程非常简单,非常可靠,但是需要注意的是——需要额外剩余足够的磁盘空间(原表大小 + 索引 + 额外的日志表空间)。

pgcompacttable

在执行INSERT和UPDATE操作时,会将所有新版本的行移到表最开始的可用空间。此为pgcompacttable工具的关键,因为如果从末端反向开始更新所有行,最终所有可用空间被这些行填充,并将表尾部的空间全部释放以便让定期vacuum进行truncate。这样一来,pgcompacttable通过批量更新和vacuum强制移动,最终整个表被重新整理,达到压缩的效果。此工具对磁盘空间要求低,且性能影响可控。


pg_repack测试

创建一个表,插入200w数据,确认我们的表的物理文件应该在 13593 这个文件夹里面,在这里我们通过oid2name 命令来查看到底你的这个表在哪里文件里面,可以看到该表占用115M


执行全表一个upate,发现表变为了230M

进行pg_repack

发现表的Filenode已经表了,表大小被收缩


pgcompacttable测试

在上个实验的基础上进行全表更新操作

表膨胀到230M

pgcompacttable操作后,表的Filenode并没有变化,且已经被收缩到115M

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论