Warum würde VACUUM ANALYZE nicht alle toten Tupel löschen?

8

Wir führen ein "Handbuch" VACUUM ANALYZE VERBOSEfür einige unserer größeren Tabellen aus, nachdem wir größere DELETE/INSERTÄnderungen an ihnen vorgenommen haben. Dies scheint ohne Probleme zu funktionieren, obwohl der VACUUMJob einer Tabelle manchmal stundenlang ausgeführt wird ( ähnliche Probleme und Überlegungen finden Sie in diesem Beitrag ).

Bei weiteren Nachforschungen stellte ich fest, dass wir auch nach dem Ausführen große Tische mit einer großen Anzahl toter Tupel haben VACUUM. Hier sind beispielsweise einige der Statistiken, die aus der Abfrage in dieser Antwort generiert wurden .

-[ RECORD 50 ]--+---------------------------
relname         | example_a
last_vacuum     | 2014-09-23 01:43
last_autovacuum | 2014-08-01 01:19
n_tup           |    199,169,568
dead_tup        |    111,048,906
av_threshold    |     39,833,964
expect_av       | *
-[ RECORD 51 ]--+---------------------------
relname         | example_b
last_vacuum     | 2014-09-23 01:48
last_autovacuum | 2014-08-30 12:40
n_tup           |    216,596,624
dead_tup        |    117,224,220
av_threshold    |     43,319,375
expect_av       | *
-[ RECORD 52 ]--+---------------------------
relname         | example_c
last_vacuum     | 2014-09-23 01:55
last_autovacuum | 2014-09-23 18:25
n_tup           |    309,831,136
dead_tup        |    125,047,233
av_threshold    |     61,966,277
expect_av       | *

Das letzte Feld gibt an, dass diese (und die meisten Tabellen) den Schwellenwert für das Autovakuum erfüllen würden. Sollte VACUUM ANALYZE VEBOSEdie Anzahl der toten Tupel nicht 0 sein (oder nahe 0, nicht 125M von 300M) , nachdem sie gerade für jede dieser Tabellen ausgeführt wurden?

In der Dokumentation heißt es:

VACUUM gewinnt Speicherplatz zurück, der von toten Tupeln belegt ist.

Bedeutet das, dass unser VACUUMnicht funktioniert?


AKTUALISIEREN

Auf Anfrage in Antwort hier sind einige Protokolle von den VERBOSEJobs:

INFO:  vacuuming "public.example_1"
INFO:  scanned index "idx_example_1_on_gp_id_and_dd_id" to remove 378386 row versions
DETAIL:  CPU 1.83s/3.42u sec elapsed 23.01 sec.
INFO:  scanned index "index_example_1_on_q_id" to remove 378386 row versions
DETAIL:  CPU 2.10s/3.91u sec elapsed 18.92 sec.
INFO:  "example_1": removed 378386 row versions in 7085 pages
DETAIL:  CPU 0.09s/0.05u sec elapsed 0.19 sec.
INFO:  index "idx_example_1_on_gp_id_and_dd_id" now contains 30347438 row versions in 291065 pages
DETAIL:  378386 index row versions were removed.
165587 index pages have been deleted, 164287 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  index "index_example_1_on_q_id" now contains 30347438 row versions in 333287 pages
DETAIL:  378386 index row versions were removed.
152773 index pages have been deleted, 152757 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "example_1": found 1773 removable, 401984 nonremovable row versions in 14438 out of 1493006 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 10567 unused item pointers.
0 pages are entirely empty.
CPU 4.26s/7.51u sec elapsed 46.10 sec.
INFO:  vacuuming "pg_toast.pg_toast_17917"
INFO:  index "pg_toast_17917_index" now contains 0 row versions in 1 pages
DETAIL:  0 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "pg_toast_17917": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  analyzing "public.example_1"
INFO:  "example_1": scanned 30000 of 1493006 pages, containing 611502 live rows and 0 dead rows; 30000 rows in sample, 40563141 estimated total rows

Diese Tabelle zeigt jetzt 0 tote Tupel in den Statistiken. Die meisten Tische sind heute Morgen viel niedrigere tote Tupel, also VACUUMfunktioniert entweder unser oder das Autovakuum.

Wir haben eine Handvoll Tabellen, die nichts ausgeben und dennoch tote Tupel zeigen:

-[ RECORD 49 ]--+---------------------------
relname         | example_2
last_vacuum     | 2014-09-23 02:23
last_autovacuum | 2014-09-02 14:30
n_tup           |    117,914,944
dead_tup        |     34,507,388
av_threshold    |     23,583,039
expect_av       | *

Ein paar Mal habe ich in den Protokollen gesehen, wo die Indizes immer wieder überprüft werden. Dies scheint lang laufenden VACUUMJobs zu entsprechen . Irgendeine Idee warum? Funktioniert dies nur um das Sperren von Datensätzen (ich glaube nicht, dass während dieses Joblaufs Schreibvorgänge stattgefunden haben).

INFO:  vacuuming "public.example_2"
...
INFO:  scanned index "index_example_2_on_gsg_id_and_dd_id" to remove 2795959 row versions
DETAIL:  CPU 3.88s/16.54u sec elapsed 23.09 sec.
INFO:  scanned index "index_example_2_on_q_id" to remove 2795959 row versions
DETAIL:  CPU 6.74s/21.13u sec elapsed 84.64 sec.
INFO:  "example_2": removed 2795959 row versions in 48214 pages
DETAIL:  CPU 0.71s/0.32u sec elapsed 33.65 sec.
INFO:  scanned index "index_example_2_on_gsg_id_and_dd_id" to remove 2591011 row versions
DETAIL:  CPU 2.84s/16.11u sec elapsed 19.28 sec.
INFO:  scanned index "index_example_2_on_q_id" to remove 2591011 row versions
DETAIL:  CPU 5.46s/22.70u sec elapsed 130.57 sec.
INFO:  "example_2": removed 2591011 row versions in 45539 pages
DETAIL:  CPU 0.67s/0.38u sec elapsed 15.16 sec.
INFO:  index "index_example_2_on_gsg_id_and_dd_id" now contains 123807784 row versions in 1560915 pages
DETAIL:  108836958 index row versions were removed.
1100790 index pages have been deleted, 718471 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.25 sec.
INFO:  index "index_example_2_on_q_id" now contains 123807784 row versions in 1886087 pages
DETAIL:  110336259 index row versions were removed.
1058063 index pages have been deleted, 266983 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.07 sec.
INFO:  "example_2": found 124808 removable, 1355901 nonremovable row versions in 2086343 out of 6966379 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 7858495 unused item pointers.
0 pages are entirely empty.
CPU 595.49s/2130.13u sec elapsed 5656.34 sec.
INFO:  vacuuming "pg_toast.pg_toast_18079"
INFO:  index "pg_toast_18079_index" now contains 0 row versions in 1 pages
DETAIL:  0 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "pg_toast_18079": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  analyzing "public.example_2"
INFO:  "example_2": scanned 30000 of 6966379 pages, containing 528443 live rows and 522 dead rows; 30000 rows in sample, 152953760 estimated total rows
Jwadsack
quelle
0 dead row versions cannot be removed yet.zeigen Sie nicht haben lange laufende Transaktionen , die Beseitigung von toten Tupeln blockieren würde.
Erwin Brandstetter

Antworten:

10

VACUUM kann nur tote Tupel entfernen, die lange tot sind, dh für alle möglichen Zwecke tot sind. Wenn Sie langlebige Transaktionen haben, können diese möglicherweise verhindern, dass die kürzlich toten Tupel entfernt werden.

Dies ist ein Beispiel für eine Situation, in der eine langlebige Transaktion das Entfernen verhinderte:

INFO:  "pgbench_accounts": found 0 removable, 2999042 nonremovable row versions in 49181 out of 163935 pages
DETAIL:  2999000 dead row versions cannot be removed yet.

Es sind keine wirklich langlebigen Transaktionen, sondern langlebige Schnappschüsse. Sicherlich wird eine lang laufende select- oder insert-Anweisung dies tun. Bei höheren Isolationsstufen als "Read Commit" behält die gesamte Transaktion den Snapshot bei, bis er nicht mehr verfügbar ist. Wenn also einige eine wiederholbare Lesetransaktion öffnen und dann in den Urlaub fahren, ohne sie festzuschreiben, ist dies ein Problem. Aufgehängte vorbereitete Transaktionen werden ebenfalls angezeigt (wenn Sie nicht wissen, was eine vorbereitete Transaktion ist, verwenden Sie sie wahrscheinlich nicht).

Die Beispiele, die Sie zeigen, weisen nicht auf ein Problem hin, aber Sie sagen auch, dass das Problem bis dahin behoben war. Wenn dies ein wiederkehrendes Problem ist, sollten Sie wahrscheinlich mit der Protokollierung der Ausgabe Ihrer VACUUM VERBOSE-Anweisungen beginnen, damit Sie die Informationen finden, die den Zeitraum abdecken, in dem das Problem besteht.

Die mehrfachen Durchläufe über den Index sind auf Ihre Einstellungen für wartungsarbeitsmaterial zurückzuführen. Es kann nur ein Tupel pro 6 Byte Speicher bei jedem Durchlauf über den Index entfernen und muss mehrere Durchgänge ausführen, wenn Sie mehr als das entfernen müssen. Daher hilft es, die Anzahl der Wartungsarbeiten zu erhöhen.

jjanes
quelle
Können Sie ein Beispiel dafür geben, was eine "langlebige Transaktion" sein könnte? Meinen Sie eine lange laufende Datenbankabfrage oder INSERT/ IMPORT? Oder meinst du etwas länger als ein Öffnen / Schließen einer Verbindung?
Jwadsack
4

Die Größe der physischen Tabelle wird normalerweise (mit Ausnahme des opportunistischen Bereinigens entfernbarer Seiten vom Ende der Tabelle) nicht durch Ausführen VACUUM(oder VACUUM ANALYZE) verringert . Sie müssen laufen VACUUM FULL, um die Tabelle tatsächlich zu verkleinern.

Dies ist ein Zitat aus der zugehörigen Antwort, die weitere Details enthält:

Pro Dokumentation (eigentlich nur ein paar Zeilen unter Ihrem Angebot):

Plain VACUUM(ohne FULL) beansprucht einfach Platz zurück und stellt ihn zur Wiederverwendung zur Verfügung. Diese Form des Befehls kann parallel zum normalen Lesen und Schreiben der Tabelle ausgeführt werden, da keine exklusive Sperre erhalten wird. Es wird jedoch (in den meisten Fällen) kein zusätzlicher Speicherplatz an das Betriebssystem zurückgegeben.

Mehr hier:

Sie werden an pg_repack interessiert sein , das dasselbe kann wie VACUUM FULLohne exklusive Sperren.

Erwin Brandstetter
quelle
1
Tut mir leid, wenn meine Frage nicht klar war, aber ich fragte nach den verbleibenden toten Tupeln. Ich weiß, dass VACUUMohne FULLdie Größe auf der Festplatte nicht reduzieren wird, und ich bin damit einverstanden. Ich erwähnte eine große Tabelle aufgrund des Beitrags, den ich mit der ersten Aussage verknüpft hatte, dass eine abgestimmte aggressive Vakuumstrategie ein "Gewinn ... wäre, wenn es große Tabellen gibt, deren Zeilen niemals gelöscht oder aktualisiert werden". Unsere großen Tische werden täglich gewechselt.
Jwadsack