it-swarm.com.de

Entfernt SELECT tote Zeilen wie VACUUM?

Ich habe mit VACUUM herumgespielt und ein unerwartetes Verhalten festgestellt, bei dem SELECTing Zeilen aus einer Tabelle die Arbeit zu reduzieren scheinen, die VACUUM danach zu erledigen hat.

Testdaten

Hinweis: Autovakuum ist deaktiviert

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

INSERT INTO numbers SELECT generate_series(1, 5000);

Versuch 1

Jetzt führen wir ein Update für alle Zeilen durch.

UPDATE numbers SET num = 0;

Und wenn wir VACUUM (VERBOSE) numbers; ausführen, erhalten wir,

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.

Versuch 2

Jetzt geben wir ein weiteres UPDATE aus, aber dieses Mal fügen wir danach ein SELECT hinzu.

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

Und wenn wir VACUUM (VERBOSE) numbers; ausführen, erhalten wir,

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.

Was genau passiert hier? Warum entfernt die zweite Version, die ich ausführe, nachdem SELECT tote Tupel von den besuchten Seiten entfernt hat, ganz wie VACUUM?

Ich verwende Postgres 11.3 unter macOS 10.14.5.

9
rafbm

Von dieser Beitrag auf/r/PostgreSQL bis Antwort von Laurenz Albe scheint es, dass Heap Only Tuples (HOT) -Updates verantwortlich sein könnten. Aus der Beschreibung von HOT Updates in src/backend/access/heap/README.HOT

Tatsächlich erfolgt die Speicherplatzrückgewinnung während des Tupelabrufs, wenn die Seite fast voll ist (<10% frei) und eine Puffersäuberungssperre erworben werden kann. Dies bedeutet, dass UPDATE, DELETE und SELECT Speicherplatzrückgewinnung auslösen können, jedoch häufig nicht während INSERT ... VALUES weil keine Zeile abgerufen wird.

Das Zitat ist nicht in der ursprünglichen Antwort, aber der Rest ist ein Zitat,

Führen Sie die folgende Abfrage aus, um diese Theorie zu unterstützen oder zu widerlegen:

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

Wenn n_tup_hot_upd ist größer als Null, wir haben einen Fall.

5
Evan Carroll

Im speziellen Fall einer nicht indizierten Tabelle kann SELECT die gleiche Arbeit wie VACUUM ausführen (was das Entfernen toter Zeilen betrifft).

1
jjanes