SELECT supprime-t-il les lignes mortes comme le fait VACUUM?

9

Je jouais avec VACUUMet j'ai remarqué un comportement inattendu où SELECTles lignes d'une table semblent réduire le travail VACUUMà faire par la suite.

Données de test

Remarque: le vide automatique est désactivé

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

INSERT INTO numbers SELECT generate_series(1, 5000);

Essai 1

Maintenant, nous exécutons une mise à jour sur toutes les lignes,

UPDATE numbers SET num = 0;

Et quand nous courons, VACUUM (VERBOSE) numbers;nous obtenons,

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.

Essai 2

Maintenant, nous en émettons un autre UPDATE, mais cette fois, nous en ajoutons un SELECTaprès,

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

Et quand nous courons, VACUUM (VERBOSE) numbers;nous obtenons,

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.

Que se passe-t-il exactement ici? Pourquoi la deuxième version que j'exécute, après avoir SELECTsupprimé les tuples morts des pages qu'elle visite, tout comme le VACUUMfait?

J'exécute Postgres 11.3 sur macOS 10.14.5.

rafbm
la source
2
Quel client utilisez-vous pour exécuter vos commandes? La validation automatique y est-elle activée?
mustaccio
2
Je vais supprimer la question "La table VACUUM est-elle simplement SELECT * FROM table sous le capot?" (ce n'est pas) Je pense que c'est un bon suivi, la réponse ici est simplement que SELECT peut supprimer les lignes mortes, et il partage cela en commun avec VACUUM. Comment ils sont différents sera une conversation très exhaustive sur le roulement XID, et une tonne d'autres choses. Cette question est essentiellement "Quelles sont les autres choses que le vide fait en plus de supprimer les lignes mortes." (Ce qui serait un peu vague)
Evan Carroll
@mustaccio J'ai fait ces tests avec un script Ruby en utilisant ActiveRecord, qui utilise la gemme PG sous le capot. Je pense que la validation automatique est activée par défaut car vous n'avez pas besoin d'émettre de COMMIT sauf si BEGIN est utilisé explicitement.
rafbm

Réponses:

5

De ce post sur / r / PostgreSQL à une réponse de Laurenz Albe, il semble que les mises à jour Heap Only Tuples (HOT) peuvent être responsables. D'après la description des mises à jour HOT danssrc/backend/access/heap/README.HOT

En effet, la récupération d'espace se produit pendant la récupération de tuple lorsque la page est presque pleine (<10% gratuite) et un verrou de nettoyage de tampon peut être acquis. Cela signifie que UPDATE, DELETEet SELECTpeut déclencher la récupération d'espace, mais souvent pas pendant, INSERT ... VALUEScar il ne récupère pas de ligne.

La citation n'est pas dans la réponse d'origine, mais le reste est une citation,

Pour soutenir ou réfuter cette théorie, exécutez la requête suivante:

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

Si n_tup_hot_updest supérieur à zéro, nous avons un cas.

Evan Carroll
la source
Nous parlons maintenant. +1
mustaccio
HOT semble être une bonne explication. Si I CREATE INDEX idx_numbers ON numbers USING btree (num), la sortie VACUUM passe à INFO: "numbers": removed 5000 row versions in 45 pages. Notez cependant que dans le scénario sans index, n_tup_hot_updest toujours 0, à la fois entre UPDATE et SELECT et entre SELECT et VACUUM. J'ai également veillé à exécuter SELECT pg_sleep(10)entre chaque instruction afin que les statistiques soient à jour (je vois seq_scan: 2, une pour la mise à jour et une pour le SELECT).
rafbm
La sélection génère-t-elle WAL dans ce cas? J'avais l'impression que les sélections ne génèrent pas du tout de WAL. Si oui, cela signifierait que la suppression des lignes mortes est propagée à tous les esclaves. Si non, cela signifie que l'aspiration est toujours nécessaire sur l'esclave. Cela signifierait également que les maîtres et les esclaves ne sont pas identiques. Hmm, j'ai peut-être besoin de faire des recherches et de poster une question et / ou une réponse ou deux.
Colin 't Hart
1

Dans le cas particulier d'une table non indexée, oui, SELECT peut faire le même travail que VACUUM (en ce qui concerne la suppression des lignes mortes).

jjanes
la source
3
Pourriez-vous ajouter une explication?
Laurenz Albe