Entfernt SELECT tote Zeilen wie VACUUM?

9

Ich spielte mit VACUUMund bemerkte ein unerwartetes Verhalten, bei dem SELECTZeilen aus einer Tabelle die Arbeit zu reduzieren scheinen, die VACUUMdanach zu erledigen ist.

Testdaten

Hinweis: Das automatische Vakuum 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 rennen VACUUM (VERBOSE) numbers;, bekommen 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 eine andere heraus UPDATE, aber dieses Mal fügen wir eine SELECTnachträgliche hinzu,

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

Und wenn wir rennen VACUUM (VERBOSE) numbers;, bekommen 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 funktioniert die zweite Version, die ich nach dem SELECTEntfernen toter Tupel von den besuchten Seiten ausführe , ganz so VACUUM?

Ich verwende Postgres 11.3 unter macOS 10.14.5.

rafbm
quelle
2
Mit welchem ​​Client führen Sie Ihre Befehle aus? Ist Autocommit darin aktiviert?
Mustaccio
2
Ich werde die Frage "Ist die VACUUM-Tabelle im Grunde nur SELECT * FROM-Tabelle unter der Haube?" Löschen. (ist es nicht) Ich denke, das ist eine gute Fortsetzung. Die Antwort hier ist einfach, dass SELECT tote Zeilen entfernen kann, und das teilt es mit VACUUM. Wie unterschiedlich sie sind, wird ein sehr ausführliches Gespräch über XID-Rollover und eine Menge anderer Dinge sein. Diese Frage lautet im Grunde: "Was macht Vakuum neben dem Entfernen toter Reihen noch?" (Was irgendwie vage wäre)
Evan Carroll
@mustaccio Ich habe diese Tests mit einem Ruby-Skript unter Verwendung von ActiveRecord durchgeführt, das das PG-Juwel unter der Haube verwendet. Ich glaube, Autocommit ist standardmäßig aktiviert, da Sie kein COMMIT ausgeben müssen, es sei denn, BEGIN wird explizit verwendet.
Rafbm

Antworten:

5

Von diesem Beitrag auf / r / PostgreSQL bis zu einer Antwort von Laurenz Albe scheint es, dass Heap Only Tuples (HOT) -Updates verantwortlich sein könnten. Aus der Beschreibung der HOT-Updates insrc/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, DELETEund SELECTeine Speicherplatzrückgewinnung auslösen kann, jedoch häufig nicht während, INSERT ... VALUESda 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_updgrößer als Null ist, haben wir einen Fall.

Evan Carroll
quelle
Jetzt reden wir. +1
Mustaccio
HOT scheint eine gute Erklärung zu sein. Wenn I CREATE INDEX idx_numbers ON numbers USING btree (num), wechselt die VACUUM-Ausgabe zu INFO: "numbers": removed 5000 row versions in 45 pages. Beachten Sie jedoch, dass im Szenario ohne Index n_tup_hot_updimmer 0 ist, sowohl zwischen UPDATE und SELECT als auch zwischen SELECT und VACUUM. Ich habe auch darauf geachtet, SELECT pg_sleep(10)zwischen den einzelnen Anweisungen zu laufen , damit die Statistiken auf dem neuesten Stand sind (ich sehe seq_scan: 2, eine für das UPDATE und eine für das SELECT).
Rafbm
Erzeugt die Auswahl in diesem Fall WAL? Ich hatte den Eindruck, dass Selects überhaupt keine WAL generieren. Wenn ja, würde dies bedeuten, dass das Entfernen von toten Zeilen an alle Slaves weitergegeben wird. Wenn nein, bedeutet dies, dass am Slave noch Staubsaugen erforderlich ist. Es würde auch bedeuten, dass Master und Slaves nicht identisch sind. Hmm, vielleicht muss ich etwas recherchieren und ein oder zwei Fragen und / oder Antworten posten.
Colin 't Hart
1

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

jjanes
quelle
3
Könnten Sie eine Erklärung hinzufügen?
Laurenz Albe