Pourquoi VACUUM ANALYZE n'effacerait-il pas tous les tuples morts?

8

Nous exécutons un «manuel» VACUUM ANALYZE VERBOSEsur certaines de nos tables plus volumineuses après y avoir DELETE/INSERTapporté des modifications majeures . Cela semble fonctionner sans problème, bien que parfois le VACUUMtravail d' une table s'exécute pendant des heures (voir ce post pour des problèmes et un raisonnement similaires).

En faisant plus de recherches, j'ai trouvé que nous avons de grandes tables avec un grand nombre de tuples morts même après l'exécution VACUUM. Par exemple, voici certaines des statistiques produites à partir de la requête dans cette réponse .

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

Le dernier champ indique que ceux-ci (et la plupart des tableaux) atteindraient le seuil d'autovacuum. Cependant, après avoir simplement exécuté VACUUM ANALYZE VEBOSEsur chacune de ces tables, le nombre de tuples morts ne devrait-il pas être 0 (ou proche de 0, pas 125M de 300M)?

La documentation indique:

VACUUM récupère le stockage occupé par les tuples morts.

Est-ce à dire que notre VACUUMne fonctionne pas?


MISE À JOUR

Par requête en repsonse voici quelques logs des 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

Ce tableau affiche désormais 0 tuples morts dans les statistiques. La plupart des tables sont des tuples morts beaucoup plus bas ce matin, donc notre VACUUMou notre aspirateur fonctionne.

Nous avons une poignée de tables qui ne produisent rien et affichent toujours des tuples morts:

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

J'ai vu plusieurs fois dans les journaux où les index seront vérifiés encore et encore. Cela semble correspondre à des VACUUMemplois de longue durée . Une idée pourquoi? Est-ce que cela fonctionne uniquement autour du verrouillage des enregistrements (je ne pense pas que des écritures se soient produites pendant l'exécution de ces travaux)

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
la source
0 dead row versions cannot be removed yet.indique que vous n'avez pas de transactions longues qui bloqueraient la suppression des tuples morts.
Erwin Brandstetter du

Réponses:

10

VACUUM ne peut supprimer que les tuples morts qui sont morts depuis longtemps, c'est-à-dire morts pour toutes les utilisations possibles. Si vous avez des transactions de longue durée, elles peuvent empêcher la suppression des tuples récemment morts.

Voici un exemple de situation où une transaction de longue durée a empêché la suppression:

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.

Ce ne sont pas vraiment des transactions de longue durée, mais des instantanés de longue durée. Une instruction select ou insert longue fera certainement cela. Pour des niveaux d'isolement supérieurs à ceux validés en lecture, l'ensemble de la transaction conservera l'instantané jusqu'à ce qu'il soit arrêté, donc si certains ouvrent une transaction de lecture répétable et partent en vacances sans la valider, ce serait un problème. Les transactions préparées bloquées le seront également (si vous ne savez pas ce qu'est une transaction préparée, vous ne les utilisez probablement pas).

Les exemples que vous montrez n'indiquent pas un problème, mais vous dites également que le problème a été résolu d'ici là. S'il s'agit d'un problème récurrent, vous devriez probablement commencer à enregistrer la sortie de vos instructions VACUUM VERBOSE, afin de pouvoir trouver les informations qui couvrent la période pendant laquelle le problème existe.

Les passages multiples sur l'index sont dus à vos paramètres de maintenance_work_mem. Il ne peut supprimer qu'un tuple pour 6 octets de mémoire à chaque passage sur l'index, et doit effectuer plusieurs passages si vous devez supprimer plus que cela. Donc, augmenter maintenance_work_mem aidera.

jjanes
la source
Pouvez-vous donner un exemple de ce que pourraient être des «transactions de longue durée»? Voulez-vous dire une longue requête de base de données ou INSERT/ IMPORT? Ou voulez-vous dire quelque chose de plus long qu'une connexion ouverte / fermée?
jwadsack
4

La taille de la table physique est généralement (sauf pour l'élagage opportuniste des pages amovibles à la fin de la table) non réduite en exécutant VACUUM(ou VACUUM ANALYZE). Vous devez exécuter VACUUM FULLpour réduire réellement la table.

Ceci est une citation de la réponse connexe, qui contient plus de détails:

Par documentation (juste quelques lignes sous votre devis, en fait):

Plain VACUUM(sans FULL) récupère simplement l'espace et le rend disponible pour la réutilisation. Cette forme de la commande peut fonctionner en parallèle avec la lecture et l'écriture normales de la table, car un verrou exclusif n'est pas obtenu. Cependant, l'espace supplémentaire n'est pas renvoyé au système d'exploitation (dans la plupart des cas);

Plus ici:

Vous serez intéressé par pg_repack , qui peut faire la même chose que VACUUM FULLsans verrous exclusifs.

Erwin Brandstetter
la source
1
Désolé si ma question n'était pas claire, mais je posais des questions sur les tuples morts restants. Je sais que VACUUMsans FULLne réduira pas la taille du disque, et ça me va. J'ai mentionné une grande table en raison du message que j'ai lié au premier, déclarant qu'une stratégie de vide agressif réglée serait une «victoire ... s'il y a de grandes tables dont les lignes ne sont jamais supprimées ni mises à jour». Nos grandes tables sont changées quotidiennement.
jwadsack