web-dev-qa-db-fra.com

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

Je jouais avec VACUUM et j'ai remarqué un comportement inattendu où SELECT ing lignes d'une table semble réduire le travail que VACUUM doit 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 lorsque nous exécutons 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 émettons un autre UPDATE, mais cette fois nous ajoutons un SELECT par la suite,

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

Et lorsque nous exécutons 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 que SELECT supprime les tuples morts des pages qu'elle visite, tout comme VACUUM?

J'utilise Postgres 11.3 sur macOS 10.14.5.

9
rafbm

De ce post sur/r/PostgreSQL à réponse de Laurenz Albe il semble que les mises à jour Heap Only Tuples (HOT) puissent être responsables. D'après la description de Mises à jour CHAUDES dans src/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% gratuit) et un verrou de nettoyage de tampon peut être acquis. Cela signifie que UPDATE, DELETE et SELECT peuvent déclencher la récupération d'espace, mais souvent pas pendant INSERT ... VALUES car 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_upd est supérieur à zéro, nous avons un cas.

5
Evan Carroll

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).

1
jjanes