Perché VACUUM ANALYZE non cancella tutte le tuple morte?


8

Eseguiamo un "manuale" VACUUM ANALYZE VERBOSEsu alcune delle nostre tabelle più grandi dopo aver DELETE/INSERTapportato importanti modifiche ad esse. Questo sembra funzionare senza problemi anche se a volte il VACUUMlavoro di una tabella verrà eseguito per ore (vedi questo post per problemi e ragionamenti simili).

Facendo ulteriori ricerche ho scoperto che abbiamo grandi tavoli con un gran numero di tuple morte anche dopo l'esecuzione VACUUM. Ad esempio, ecco alcune delle statistiche prodotte dalla query in questa risposta .

-[ 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       | *

L'ultimo campo indica che queste (e la maggior parte delle tabelle) soddisfano la soglia per il vuoto automatico. Tuttavia, avendo appena eseguito VACUUM ANALYZE VEBOSEsu ciascuna di quelle tabelle, il conteggio delle tuple morte non dovrebbe essere 0 (o vicino a 0, non 125 M di 300 M)?

La documentazione afferma:

VACUUM recupera la memoria occupata da tuple morte.

Questo significa che il nostro VACUUMnon funziona?


AGGIORNARE

Per richiesta in risposta ecco alcuni registri dai VERBOSElavori:

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

Questa tabella ora mostra 0 tuple morte nelle statistiche. La maggior parte dei tavoli sono tuple morte molto più basse stamattina, quindi il nostro VACUUMo il vuoto automatico funziona.

Abbiamo una manciata di tabelle che non generano nulla e mostrano ancora tuple morte:

-[ 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       | *

Un paio di volte ho visto nei registri dove gli indici verranno controllati più e più volte. Questo sembra corrispondere a lavori di lunga durata VACUUM. Qualche idea sul perché? Sta solo lavorando intorno al blocco dei record (non penso che ci fossero delle scritture durante questa esecuzione di lavori).

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

0 dead row versions cannot be removed yet.indica che non hai transazioni a lungo termine che potrebbero bloccare la rimozione di tuple morte.
Erwin Brandstetter,

Risposte:


10

VACUUM può rimuovere solo tuple morte che sono morte da lungo tempo, cioè morte per tutti gli usi possibili. Se hai transazioni di lunga durata, potrebbero impedire la rimozione delle tuple recentemente morte.

Questo è un esempio di una situazione in cui una transazione di lunga durata ha impedito la rimozione:

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.

Non si tratta di transazioni di lunga durata, ma di istantanee di lunga durata. Certamente un'istruzione select o insert di lunga durata lo farà. Per livelli di isolamento superiori a quelli sottoposti a commit in lettura, l'intera transazione manterrà lo snapshot fino a quando non sarà inattivo, quindi se alcuni aprono una transazione di lettura ripetibile e poi vanno in vacanza senza impegnarsi, ciò sarebbe un problema. Anche le transazioni preparate con il riaggancio (se non sai cos'è una transazione preparata, probabilmente non le stai usando).

Gli esempi che mostri non indicano un problema, ma dici anche che il problema si era risolto da allora. Se si tratta di un problema ricorrente, probabilmente dovresti iniziare a registrare l'output delle tue istruzioni VACUUM VERBOSE, in modo da poter trovare le informazioni che coprono il periodo durante il quale esiste il problema.

I passaggi multipli sull'indice sono dovuti alle impostazioni di maintenance_work_mem. Può rimuovere solo una tupla per ogni 6 byte di memoria su ogni passaggio sull'indice e deve effettuare più passaggi se è necessario rimuovere più di quello. Quindi aumentare la manutenzione_work_mem aiuterà.


Potete fornire un esempio di ciò che potrebbe essere una "transazione di lunga durata"? Intendi una query di database a esecuzione prolungata o INSERT/ IMPORT? O intendi qualcosa di più lungo di una connessione aperta / chiusa?
jwadsack,

4

La dimensione della tabella fisica è in genere (ad eccezione della potatura opportunistica delle pagine rimovibili dalla fine della tabella) non ridotta eseguendo VACUUM(o VACUUM ANALYZE). È necessario eseguire VACUUM FULLper ridurre effettivamente la tabella.

Questa è una citazione dalla risposta correlata, che ha maggiori dettagli:

Per documentazione (in realtà solo poche righe sotto il tuo preventivo):

Plain VACUUM(senza FULL) semplicemente recupera lo spazio e lo rende disponibile per il riutilizzo. Questa forma del comando può funzionare in parallelo con la normale lettura e scrittura della tabella, poiché non si ottiene un blocco esclusivo. Tuttavia, lo spazio aggiuntivo non viene restituito al sistema operativo (nella maggior parte dei casi);

Più qui:

Ti interesserà pg_repack , che può fare lo stesso VACUUM FULLsenza blocchi esclusivi.


1
Scusate se la mia domanda non era chiara, ma stavo chiedendo delle rimanenti tuple morte. So che VACUUMsenza FULLnon ridurrà le dimensioni sul disco, e sto bene con quello. Ho menzionato una tabella di grandi dimensioni a causa del post che ho collegato alla prima affermando che una strategia di vuoto aggressivo ottimizzata sarebbe una "vittoria ... se ci sono tabelle di grandi dimensioni le cui righe non vengono mai cancellate né aggiornate". I nostri tavoli di grandi dimensioni vengono cambiati ogni giorno.
jwadsack,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.