SELECTは、VACUUMのようにデッド行を削除しますか?


9

私はいじくり回していて、テーブルから行をingすることで、後で行う必要のある作業が減るようVACUUMな予期しない動作に気づきました。SELECTVACUUM

テストデータ

注:自動バキュームは無効になっています

CREATE TABLE numbers (num bigint);
ALTER TABLE numbers SET (
  autovacuum_enabled = 'f',
  toast.autovacuum_enabled = 'f'
);

INSERT INTO numbers SELECT generate_series(1, 5000);

試験1

次に、すべての行に対して更新を実行します。

UPDATE numbers SET num = 0;

そして走るVACUUM (VERBOSE) numbers;と、

INFO:  vacuuming "public.numbers"
INFO:  "numbers": removed 5000 row versions in 23 pages
INFO:  "numbers": found 5000 removable, 5000 nonremovable row versions in 45 out of 45 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 6585
There were 0 unused item pointers.

試験2

次にUPDATE、別のを発行しますが、今回はSELECT後で追加します。

UPDATE numbers SET num = 1;
SELECT * FROM numbers;

そして走るVACUUM (VERBOSE) numbers;と、

INFO:  vacuuming "public.numbers"
INFO:  "numbers": removed 56 row versions in 22 pages
INFO:  "numbers": found 56 removable, 5000 nonremovable row versions in 45 out of 45 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 6586
There were 56 unused item pointers.

ここで何が起こっているのですか?なぜ私が実行する2番目のバージョンは、SELECTアクセスするページから不要なタプルを削除した後、まったく同じようにVACUUM実行するのですか?

MacOS 10.14.5でPostgres 11.3を実行しています。


2
コマンドを実行するためにどのクライアントを使用していますか?オートコミットは有効になっていますか?
Mustaccio

2
「VACUUMテーブルは、基本的には内部的にSELECT * FROMテーブルだけですか?」という質問を削除します。(そうではありません)私はそれが良いフォローアップだと思います。ここでの答えは、SELECTがデッド行を削除できることであり、VACUUMと共通しています。それらがどのように異なるかは、XIDロールオーバーについての非常に徹底的な会話であり、他にもたくさんのものがあります。その質問は基本的に「死んだ行を削除する以外にバキュームは他に何をするか」です。(どちらかというと漠然となるでしょう)
Evan Carroll

@mustaccio私はこれらのテストを、内部でPG gemを使用するActiveRecordを使用するRubyスクリプトで行いました。BEGINを明示的に使用しない限り、COMMITを発行する必要がないため、デフォルトで自動コミットが有効になっていると思います。
rafbm

回答:


5

/ r / PostgreSQLのこの投稿からLaurenz Albeの回答まで、ヒープのみのタプル(HOT)の更新が原因である可能性があります。のHOTアップデートの説明よりsrc/backend/access/heap/README.HOT

事実上、スペースの再生は、ページがほぼ満杯(10%未満)であるタプルの取得中に発生し、バッファーのクリーンアップロックを取得できます。この手段ものUPDATEDELETESELECTの間にスペース再利用を誘発するが、多くの場合することはできませんINSERT ... VALUES、それは行を取得していないため。

引用は元の答えにはありませんが、残りは引用です、

この理論を支持または否定するには、次のクエリを実行します。

SELECT n_tup_upd, n_tup_hot_upd
FROM pg_stat_user_tables
WHERE schemaname = 'public' AND relname = 'TABLE_NAME';

n_tup_hot_updがゼロより大きい場合は、ケースがあります。


今、話しています。+1
Mustaccio

HOTは良い説明のようです。Iの場合CREATE INDEX idx_numbers ON numbers USING btree (num)、VACUUM出力はに変わりますINFO: "numbers": removed 5000 row versions in 45 pages。ただし、インデックスのないシナリオでn_tup_hot_updは、UPDATEとSELECTの間、およびSELECTとVACUUMの間は常に0であることに注意してください。またSELECT pg_sleep(10)、統計が最新になるように、各ステートメント間で実行することも確認しました(seq_scan: 21つはUPDATE用で、もう1つはSELECT用です)。
rafbm

この場合、selectはWALを生成しますか?「WALをまったく生成しない」を選択するという印象を受けました。はいの場合、これはデッド行の削除がスレーブに伝播されることを意味します。いいえの場合、これはスレーブでバキューム処理がまだ必要であることを意味します。また、マスターとスレーブが少し同じではないことも意味します。うーん、たぶん私はいくつかの調査を行い、質問および/または答えを投稿する必要があります。
Colin 't Hart

1

インデックスのないテーブルの特別なケースでは、はい、SELECTはVACUUMと同じ処理を実行できます(デッド行の削除に関する限り)。


3
説明を追加してもらえますか?
ローレンツアルベ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.