微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

postgresql – 在仅接收INSERT的表上运行VACUUM是否值得?

在2015年的re:Invent谈话中,AWS提到真空应该不仅在更新或删除之后运行,而且在插入之后运行.以下是谈话的相关部分:

http://www.youtube.com/watch?v=tZXp19q8RFo&t=16m2s

据说有一些清理必须在块上完成,即使它们只接收到插入,并且可以在第一次选择块(减慢读取)或在真空期间进行清理.这是真的,如果是的话,究竟要做什么清理?

tl; dr:在提交数据后读取数据的第一个进程将设置提示位.这将弄脏页面,创建写入活动. VACUUM(但不是其他命令)做的另一件事是将页面标记为全部可见,如果合适的话. VACUUM最终将不得不在桌面上冻结元组.

插入后需要完成的工作不是真正清理,至少不是VACUUM通常做的其他工作.在我详细介绍之前,请注意这个答案是基于当前(未发布的)9.6代码,我忽略了流复制的影响,即使它可能会影响可见性.

因为MVCC,每次Postgres评估一个元组是否应该对查询可见时,它必须考虑是否提交了创建元组的事务(记录在xmin隐藏字段中)以及其他一些标准.该检查很昂贵,因此只要知道所有当前打开的事务都可以看到事务,就会在元组头上设置“提示位”来指示该事务.该位的设置会弄脏页面,这意味着必须将其写入磁盘.如果读取数据的下一个命令是突然创建大量写入流量的SELECT,则这可能会非常混乱.在insert提交后运行VACUUM将避免这种情况.另一个重要的区别是VACUUM将始终在页面提示元组(只要它在页面上获得清理锁定),但大多数其他命令只会提示如果在命令启动之前提交插入事务.

写入所有这些提示位的一个重点是可以限制VACUUM(并且认情况下会禁止autovacuum).其他命令不受限制,并将尽快生成脏数据.

VACUUM是将页面标记为全可见的唯一方法,这是某些操作(特别是仅索引扫描)的重要性能考虑因素.如果你做一个大的插入,很可能有很多页面只有新插入的元组. VACUUM可能会将这些页面标记为全部可见,但前提是VACUUM启动时最早运行的事务比插入数据的事务更新.

由于MVCC的工作方式,插入超过20亿次交易之前的元组必须标记为“frozen”.认情况下,autovacuum将启动每200M事务.在批量插入后将vacuum_freeze_min_age设置为0运行手动真空有助于减少其影响.更积极的是,您可以在插入后在桌面上运行VACUUM FREEZE.这将在下一次冻结扫描发生时“重置时钟”.

如果您想了解具体细节,请在lazy_scan_heap()内调用HeapTupleSatisfiesVacuum()后查看HEAPTUPLE_LIVE案例.另请参阅HeapTupleSatisfiesVacuum()本身,并将其与HeapTupleSatisfiesMVCC()进行比较.

我的另外两个演讲可能很有趣.第一个视频可以从http://www.pgcon.org/2015/schedule/events/829.en.html开始,而第二个视频(我觉得有点好)可以在https://www.youtube.com/watch?v=L8nErzxPJjQ

原文地址:https://www.jb51.cc/postgresql/192453.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐