Image de couverture : Autovacuum PostgreSQL : pourquoi le désactiver est une erreur que vous regretterez
tech

Autovacuum PostgreSQL : pourquoi le désactiver est une erreur que vous regretterez

10 May 2026
6 min de lecture
22 vues
Sébastien Muler

Autovacuum PostgreSQL : pourquoi le désactiver est une erreur que vous regretterez

Dans l'écosystème PHP/Symfony, PostgreSQL est souvent le choix de prédilection pour sa robustesse et ses fonctionnalités avancées. Pourtant, un paramètre aussi fondamental qu'autovacuum est régulièrement mal compris — voire désactivé — avec des conséquences parfois catastrophiques sur les performances. Cet article s'appuie sur une analyse publiée par Christophe Pettus (source originale) pour vous expliquer ce qu'est autovacuum, pourquoi vous ne devez jamais le désactiver, et comment le configurer intelligemment.


Qu'est-ce qu'autovacuum et pourquoi est-il indispensable ?

autovacuum est un paramètre booléen de PostgreSQL, activé par défaut (on), dont le contexte d'application est sighup. Concrètement, il pilote un processus de fond qui lance automatiquement les commandes VACUUM et ANALYZE sur vos tables en fonction de l'activité accumulée.

C'est le processus de maintenance le plus important de PostgreSQL. Sans lui, votre base de données accumule silencieusement des problèmes qui ne se manifesteront qu'au pire moment.

Pourtant, les raisons invoquées pour le désactiver reviennent souvent :

  • « Le vacuum cause des problèmes de performances »
  • « Ma table est en écriture seule, pas besoin de vacuum »
  • « J'ai lu sur un forum qu'il fallait le désactiver » (souvent un post de 2008...)

Aucune de ces justifications ne résiste à l'examen des conséquences réelles.


Les effets en cascade d'une désactivation

1. Bloat des tables et des index

Chaque UPDATE ou DELETE dans PostgreSQL ne supprime pas physiquement les anciennes versions des lignes. Ces tuples morts restent sur le disque jusqu'à ce que VACUUM les récupère. Sans autovacuum, votre table de 10 Go peut facilement occuper 40 Go sur le disque — avec toujours seulement 10 Go de données vivantes.

Résultat : les sequential scans ralentissent proportionnellement à la taille physique réelle. Les index B-tree souffrent du même problème : leurs pages ne récupèrent pas d'espace sans l'intervention de vacuum, ce qui dégrade progressivement les performances des requêtes indexées.

Dans une application Symfony avec Doctrine, ce phénomène est particulièrement sournois sur les entités à forte volumétrie d'écriture (logs, événements, sessions).

2. Statistiques obsolètes et mauvais plans d'exécution

Autovacuum exécute également ANALYZE, qui met à jour les statistiques utilisées par le query planner. Sans ces statistiques à jour, le planificateur de requêtes prend ses décisions sur la base de distributions de données périmées.

Une requête rapide ce mois-ci peut devenir lente le mois prochain — non pas parce que le code a changé, mais parce que le planner choisit désormais un plan d'exécution sous-optimal. Ce type de régression est particulièrement difficile à diagnostiquer car la dégradation est graduelle.

3. Disparition des index-only scans

PostgreSQL maintient une visibility map pour chaque table, qui indique quelles pages contiennent exclusivement des tuples visibles par toutes les transactions. Cette map est mise à jour par vacuum et permet au planner d'utiliser les index-only scans — une optimisation qui évite de consulter le heap lorsque l'index contient toutes les colonnes nécessaires.

Sans autovacuum, la visibility map se dégrade. Le planner ne peut plus garantir que le heap visit est inutile, et les index-only scans se transforment en index scans ordinaires avec des heap fetches supplémentaires. Des chemins de lecture critiques ralentissent sans qu'une seule ligne de code n'ait changé.

4. Transaction ID Wraparound : la panne fatale ⚠️

C'est le scénario le plus grave. PostgreSQL utilise des Transaction IDs (XIDs) sur 32 bits pour gérer la visibilité des données. Lorsque le compteur approche de sa limite (~2 milliards de transactions), PostgreSQL entre en mode d'urgence et refuse toute nouvelle écriture pour protéger la cohérence des données.

Votre base de données s'arrête. Complètement. Pour toutes les écritures.

Autovacuum est précisément conçu pour exécuter des VACUUM FREEZE préventifs qui repoussent cette limite. Sans lui, vous dépendez d'opérations manuelles — et si vous les oubliez, la conséquence est une interruption de service totale.


Comment bien configurer autovacuum pour vos applications Symfony

Plutôt que de le désactiver, la bonne approche est de l'ajuster selon la charge réelle de vos tables.

Paramètres clés au niveau instance

-- Nombre de workers autovacuum (défaut : 3)
autovacuum_max_workers = 5

-- Coût maximum avant une pause (évite la saturation I/O)
autovacuum_vacuum_cost_limit = 400

-- Délai entre deux cycles de cost accounting
autovacuum_vacuum_cost_delay = 2ms

Tuning par table pour les entités à fort volume

Pour une entité Doctrine à haute fréquence d'écriture (ex : une table d'événements ou de logs) :

ALTER TABLE app_events SET (
  autovacuum_vacuum_scale_factor = 0.01,  -- Déclencher à 1% de tuples morts
  autovacuum_analyze_scale_factor = 0.005, -- Analyser à 0.5%
  autovacuum_vacuum_cost_limit = 800       -- Plus agressif sur cette table
);

Par défaut, autovacuum_vacuum_scale_factor est à 0.2 (20% de tuples morts avant déclenchement). Sur une table de 10 millions de lignes, cela représente 2 millions de tuples morts accumulés avant toute intervention — ce qui est beaucoup trop pour des applications critiques.

Surveiller l'état de vos tables

SELECT
  schemaname,
  relname,
  n_dead_tup,
  n_live_tup,
  last_autovacuum,
  last_autoanalyze
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 20;

Cette requête vous donne une vision immédiate des tables qui accumulent du bloat et de la fréquence réelle des passages d'autovacuum.


Conclusion

Autovacuum n'est pas un problème à résoudre en le désactivant — c'est une solution à configurer correctement. Désactivé, il laisse s'installer silencieusement du bloat, des statistiques obsolètes, des optimisations inopérantes et, au pire, une interruption complète de service par transaction ID wraparound.

Dans vos projets Symfony/PHP, prenez le temps d'auditer la configuration autovacuum de vos bases de données, d'identifier les tables critiques et d'ajuster les paramètres en conséquence. C'est un investissement de quelques heures qui peut vous éviter une nuit de crise.

Cet article s'inspire de l'analyse de Christophe Pettus publiée sur postgr.es, dans sa série All Your GUCs in a Row.

Partager cet article