データベースで自動バキュームのアクティビティを監視していると、(to prevent wraparound)
でタグ付けされた自動バキュームが「通常の」自動バキュームよりも時間がかかるようです。これにより、さまざまな「種類」または自動バキュームのパフォーマンス/動作の違いを理解しようとしました。
the docs から、autovacuumがテーブルをVACUUM
する理由をいくつか確認しました:
テーブルには、フリーズする必要がある古いトランザクションがあります(relfrozenxid > min(autovacuum_freeze_max_age, table.autovacuum_freeze_max_age
)。これは「(to prevent wraparound)
」の自動バキュームです。
最後のVACUUM
が「真空しきい値」を超えてからテーブルで廃止されたタプルの数
他に欠けているものはありますか?
マニュアルVACUUM
で公開されているように見える「アグレッシブネス」ノブはFREEZE
とDISABLE_PAGE_SKIPPING
です。これらのさまざまな種類の自動バキュームがこれらのオプションを使用したことはありますか?
私のデータベースでautovacuumアクティビティを監視しているときに、(ラップアラウンドを防止するために)タグが付けられたautovacuumsは、「通常の」autovacuumsより時間がかかるようです。
それは予想されることです。彼らはもっと仕事をしなければならない。これらは基本的にvacuum freeze
autovacuumによって実行されます。
タプルをフリーズするとは、トランザクションIDを特別な固定値FrozenTransactionId
(xid 3)に置き換えることにより、現在および将来のすべてのトランザクションでそれらを可視としてマークすることを意味します。タプルのxminはディスク上のタプルに格納されるため、これは、まだフリーズされておらず、フリーズの候補である各タプルを変更する必要があることを意味します。通常、タプルは最後のチェックポイント以降のページの最初の変更であるため、これによりフルページ書き込みがトリガーされ、各ページの最初のフリーズされたタプルに8kの書き込みが発生します。 (これもWALを膨らませるので、PITRバックアップ、レプリケーションストリームなど)。
PostgreSQL 9.6以前のフリーズバキュームでは、テーブルの一部をスキップできません。たとえそれがほんの少しだけ凍結の候補であっても、毎回テーブル全体をスキャンする必要があります。
Autovacuumを調整してより積極的にフリーズしない限り、強制フリーズがかなり遅くなり、すぐに多くの作業が行われる傾向があります。テーブルを何度もスキャンしないため、これは効率的ですが、処理するたびに多くの作業を行うため、コストがかかります。
バキュームがタプルを凍結していない場合でも、同じ作業の多くを実行しています。しかし、コミットされたトランザクションによってロック専用ではないxmax
が設定されているタプルのみを気にする必要があるため、通常、各パスで接触するページ数ははるかに少なくなります。これらのタプルを含むページは、最近削除されたためにキャッシュに存在する可能性が高く、それらのマルチxactデータもキャッシュに存在する可能性が高くなります。
次の方法で、真空の凍結を高速化できます。
引き下げautovacuum_vacuum_cost_delay
-これにより、autovacuumはより多くのリソースを使用し、システムにより多くの負荷をかけますが、より高速に実行されます。
下降 autovacuum_freeze_max_age
なので、より頻繁に実行され、毎回少ない作業を行います。テーブル全体を毎回スキャンする必要があり、テーブルを読み取るときにOSバッファキャッシュからページを追い出すため、これは全体的に効率が低下します。 (Pgはseqスキャンにリングバッファーを使用しますが、OSは通常使用しません)。しかし、それは各パスで行う書き込みが少なくなり、各パスにかかる時間が短くなることを意味します。
COPY
dまたはFREEZE
dと同じトランザクション内でテーブルを一括読み込みするためにTRUNCATE
オプションを使用してCREATE
を実行します。この方法でロードされたタプルは、事前に凍結された状態で始まります。 (詳細はCOPY
のマニュアルを参照してください)。
テーブルを一括読み込みした後、テーブルを手動でフリーズします。そのため、あなたが管理する時間にフリーズ費用を支払います。
個人的には、通常のVACUUM
s(およびautovacuums)でさらに便宜的なフリーズを実行したいと思います。特に、ページのアイテムポインター配列に触れて、いくつかのタプルを空き領域としてマークした場合、ページがダーティである間、おそらくフリーズ可能なタプルをスキャンする必要があります。これは、PostgreSQL 10の新しいフリーズマップコードで非常にうまく機能します。
PostgreSQL 9.6のフリーズにはいくつかの大きな改善があり、テーブルに対する繰り返しのバキュームの影響を減らし、フリーズをはるかに安価にしています。可視性マップにフリーズマップ機能が導入されたため、フリーズされたページをスキップしてテーブル全体をスキャンすることを回避できます。コミットa892234およびfd31cd265を参照してください。
commit fd31cd265138019dcccc9b5fe53043670898bc9f
Author: Robert Haas <[email protected]>
Date: Thu Mar 10 16:12:10 2016 -0500
Don't vacuum all-frozen pages.
Commit a892234f830e832110f63fc0a2afce2fb21d1584 gave us enough
infrastructure to avoid vacuuming pages where every Tuple on the
page is already frozen. So, replace the notion of a scan_all or
whole-table vacuum with the less onerous notion of an "aggressive"
vacuum, which will pages that are all-visible, but still skip those
that are all-frozen.
This should greatly reduce the cost of anti-wraparound vacuuming
on large clusters where the majority of data is never touched
between one cycle and the next, because we'll no longer have to
read all of those pages only to find out that we don't need to
do anything with them.
Patch by me, reviewed by Masahiko Sawada.
PostgreSQL 10についても、ディスク上のタプルを変更してフリーズとしてマークする必要を完全に回避する作業が進んでいると思いますが、関連するメーリングリストのスレッドatmが見つかりません。