web-dev-qa-db-ja.com

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

VACUUMをいじっていると、予期しない動作に気づき、テーブルからのSELECTing行により、VACUUMが後で実行する必要のある処理が削減されるようです。

テストデータ

注:自動バキュームは無効です

_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.
_

ここで何が起こっているのですか? SELECTVACUUMのように、アクセスしたページからデッドタプルを削除した後、2番目のバージョンを実行するのはなぜですか?

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

9
rafbm

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

実質的には、ページがほぼフル(<10%空き)であり、バッファーのクリーンアップロックを取得できる場合、タプルの取得中にスペースの再利用が発生します。つまり、UPDATEDELETE、およびSELECTはスペースの再利用をトリガーできますが、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がゼロより大きい場合は、ケースがあります。

5
Evan Carroll

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

1
jjanes