foo*_*100 19 postgresql performance vacuum postgresql-performance
在 2015 年的 re:Invent 演讲中,AWS 提到真空不仅应该在更新或删除之后运行,而且还应该在插入之后运行。这是谈话的相关部分:
http://www.youtube.com/watch?v=tZXp19q8RFo&t=16m2s
据说即使块只收到插入,也必须对块进行一些清理,并且可以在第一次选择块时(减慢读取速度)或在真空期间进行清理。这是真的吗?如果是这样,究竟必须进行哪些清理工作?
Jim*_*sby 15
tl;dr:提交后读取数据的第一个进程将设置提示位。这会弄脏页面,创建写入活动。另一件事VACUUM
(但不是其他命令)会在适当的情况下将页面标记为全可见。VACUUM
最终将不得不打表来冻结元组。
插入后需要完成的工作并不是真正的清理,至少不是其他工作VACUUM
通常所做的。在我进入细节之前,请注意这个答案是基于当前(未发布的)9.6 代码,我忽略了流复制的影响,即使它会影响可见性。
由于MVCC,每次 Postgres 评估元组是否应该对查询可见时,它必须考虑创建元组的事务(记录在 xmin 隐藏字段中)是否已提交,以及其他一些标准。该检查是昂贵的,因此一旦知道事务对所有当前打开的事务都是可见的,就会在元组标头上设置一个“提示位”来指示这一点。该位的设置会弄脏页面,这意味着必须将其写入磁盘。如果下一个读取数据的命令SELECT
突然产生大量写入流量,这可能会非常令人困惑。VACUUM
在插入提交后运行 a将避免这种情况。另一个重要的区别是VACUUM
将始终提示页面上的元组(只要它在页面上获得清理锁),但大多数其他命令只会提示插入事务是否在命令开始之前提交。
编写所有这些提示位的一个重要点是VACUUM
可以限制的(默认情况下自动清理是限制的)。其他命令不受限制,会尽快生成脏数据。
VACUUM
是将页面标记为全可见的唯一方法,这是某些操作(特别是仅索引扫描)的重要性能考虑因素。如果你做一个大的插入,很可能有很多页面只有新插入的元组。VACUUM
可以潜在地将这些页面标记为全部可见,但VACUUM
前提是启动时最旧的运行事务比插入数据的事务新。
由于 MVCC 的工作方式,在超过 20 亿笔交易之前插入的元组必须标记为“冻结”。默认情况下,autovacuum 将每 200M 事务启动一次。在批量插入后运行将vacuum_freeze_min_age 设置为0 的手动vacuum 可以帮助减少这种影响。更积极的是,您可以VACUUM FREEZE
在插入后在桌子上运行。这将在下一次冻结扫描发生时“重置时钟”。
如果你想知道具体的细节,请查看HEAPTUPLE_LIVE
调用HeapTupleSatisfiesVacuum()
inside后的案例lazy_scan_heap()
。另见HeapTupleSatisfiesVacuum()
自身,并将其与HeapTupleSatisfiesMVCC()
.
我的另外两个演讲可能很有趣。第一个视频可从http://www.pgcon.org/2015/schedule/events/829.en.html 获得,而第二个视频(我认为更好一点)在https://www.youtube 上。 com/watch?v=L8nErzxPJjQ
归档时间: |
|
查看次数: |
2817 次 |
最近记录: |