PG做update操作引起的表膨胀情况

0    25    1

Tags:

👉 本文共约1078个字,系统预计阅读时间或需5分钟。

前言

PostgreSQL数据库的MVCC机制中,一个明显的特点是,在执行DELETE操作,它一般并不立即擦除要删的数据,通常只是做一个标记,留给VACUUM进程去做相应的清理,并且是有条件的清理。

而UPDATE操作,则更是一个DELETE操作和一个INSERT操作的组合。INSERT操作则通常会APPEND一条记录在后边。这样的结果是,通常情况下,这种INSERT, UPDATE操作应该是很快的。

但如果用的不当,也有一些反例。

示例

下面看一则很普通的示例:

我们可以明显的看到,一条普通的记录,在更新100000次的操作下,居然花了整整两分钟。

我们用下边的SQL来看看该表的元组分布情况:(将其中的public.t3改为你想要的表名,就可以查目标表的相应情况)

结果如下:

发现总共只有一条记录,但是死元组居然是100000条。这些都是要占有空间的。总的表大小是3658kB,它可是只有一个整型字段啊。

其主要原因就是它一个事务里头,调用了太多的update,并且是不断的DELETE, INSERT, 在后一次的UPDATE,它要全部扫描过往的元组。

执行一次vacuum,看看:

也只是将死元组清除标记,空间上并没有立即回收。使用vacuum full,会立即回收整个空间。

如果想让上边的update速度能快一些,可以改为在循环内显式的提交事务。但似乎也改善的不太多。但是空间占用会少很多。

空间大小:

可以看到,它的大小也是有所不同的。证明在中间update操作是可以复用以前的无用空间。

再补充一个小的验证性测试,如果我们将fillfactor调整为20, 预留80%的空间给update操作,看看第1种情况下,花的时间是啥样的?(1分40秒)

本人提供Oracle(OCP、OCM)、MySQL(OCP)、PostgreSQL(PGCA、PGCE、PGCM)等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!

表相关空间大小:3576kB

循环内commit,情况如何:

空间大小:(8kB)

在实际使用当中,对于高频的更新操作的表,为减轻vacuum的负担,可以建议性的将fillfactor调整为80或75,给Update操作预留适当的空间。

参考

https://mp.weixin.qq.com/s/buq-POkC7LE4xZNSsa-g2w

https://mp.weixin.qq.com/s/xUzgTBbAbo0wgljaAP6now

标签:

头像

小麦苗

学习或考证,均可联系麦老师,请加微信db_bao或QQ646634621

您可能还喜欢...

发表回复

嘿,我是小麦,需要帮助随时找我哦
  • 18509239930
  • 个人微信

  • 麦老师QQ聊天
  • 个人邮箱
  • 点击加入QQ群
  • 个人微店

  • 回到顶部
返回顶部