
La configuration par défaut de PostgreSQL est volontairement conservatrice : 128 Mo de shared_buffers, aucun log de requête lente, pas d'écoute réseau distante. C'est un choix de sécurité et de portabilité, un PostgreSQL fraîchement installé fonctionne partout, même sur un Raspberry Pi. Mais un serveur de production avec ces réglages sous-utilise la RAM disponible, ne capture aucun événement utile au diagnostic, et peut surprendre quand le nombre de connexions augmente.
Ce guide vous montre comment adapter la configuration à votre serveur, en partant des paramètres les plus impactants. Chaque modification est testée sur un lab réel (PostgreSQL 18.3, Debian 12, 2 Go de RAM) et accompagnée de la méthode de rechargement adaptée, reload quand c'est possible, restart quand c'est obligatoire.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Localiser les fichiers de configuration et comprendre la priorité
postgresql.conf→postgresql.auto.conf - Dimensionner les 4 paramètres mémoire critiques :
shared_buffers,work_mem,maintenance_work_mem,effective_cache_size - Configurer le logging pour capturer les requêtes lentes, les connexions et les verrous
- Comprendre l'autovacuum et savoir détecter un retard
- Recharger la configuration à chaud avec
pg_reload_conf()et identifier les paramètres qui exigent un restart
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »Les cinq situations ci-dessous ont un point commun : elles surviennent toutes après l'installation, quand le serveur fonctionne mais ne se comporte pas comme votre charge de travail l'exige. Si vous êtes dans la première, traitez la mémoire et le logging avant tout le reste, ce sont les deux réglages qui changent quelque chose immédiatement.
Vous devez configurer PostgreSQL dans ces situations :
- Vous venez d'installer PostgreSQL et les valeurs par défaut ne correspondent pas à votre serveur (RAM sous-utilisée, pas de log exploitable)
- Vous mettez un serveur en production et devez garantir des performances correctes et du logging utile
- Vous devez ouvrir les connexions réseau pour qu'une application distante puisse se connecter
- Vous constatez des requêtes lentes et avez besoin de les tracer
- L'autovacuum montre des signes de retard (tables gonflées,
n_dead_tupélevé)
Ce guide ne couvre pas…
Section intitulée « Ce guide ne couvre pas… »Trois sujets voisins sont volontairement laissés de côté parce qu'ils ne se règlent pas dans postgresql.conf. Le contrôle d'accès (pg_hba.conf, TLS, rôles) obéit à sa propre logique de fichier ordonné, où la première règle qui correspond gagne. La sauvegarde relève de l'exploitation, pas du réglage. Et l'usage courant de psql est un prérequis plutôt qu'un sujet de configuration. Les cartes ci-dessous renvoient vers les guides correspondants.
Prérequis
Section intitulée « Prérequis »- PostgreSQL installé et le service actif (voir le guide Installation)
- Accès au rôle superuser (
postgres) pour modifier la configuration - Connaître les bases de psql (voir le guide Prise en main de psql)
Où se trouve la configuration ?
Section intitulée « Où se trouve la configuration ? »Par défaut, PostgreSQL place postgresql.conf et postgresql.auto.conf dans le data directory (PGDATA). Mais sur Debian/Ubuntu avec les paquets PGDG, le packaging sépare les fichiers de configuration du répertoire de données, une convention spécifique, pas une règle générale PostgreSQL. L'organisation résultante :
| Fichier | Emplacement | Rôle |
|---|---|---|
postgresql.conf | /etc/postgresql/18/main/postgresql.conf | Configuration principale du serveur |
postgresql.auto.conf | /var/lib/postgresql/18/main/postgresql.auto.conf | Écrit par ALTER SYSTEM, prioritaire |
pg_hba.conf | /etc/postgresql/18/main/pg_hba.conf | Contrôle d'accès (qui peut se connecter) |
pg_ident.conf | /etc/postgresql/18/main/pg_ident.conf | Mapping entre utilisateurs système et rôles |
Vérifiez les chemins réels avec :
SHOW config_file;SHOW hba_file;SHOW data_directory; config_file----------------------------------------- /etc/postgresql/18/main/postgresql.conf
hba_file------------------------------------- /etc/postgresql/18/main/pg_hba.conf
data_directory----------------------------- /var/lib/postgresql/18/mainpostgresql.conf : la configuration principale
Section intitulée « postgresql.conf : la configuration principale »C'est le fichier central. Il contient des centaines de paramètres, la plupart commentés (valeur par défaut). Seuls les paramètres décommentés sont effectifs.
Ce fichier est géré par l'administrateur ou un outil de gestion de configuration (Ansible, Puppet, etc.).
postgresql.auto.conf : ALTER SYSTEM écrit ici
Section intitulée « postgresql.auto.conf : ALTER SYSTEM écrit ici »Quand vous exécutez ALTER SYSTEM SET shared_buffers = '512MB';, PostgreSQL écrit la valeur dans postgresql.auto.conf, jamais dans postgresql.conf.
# Do not edit this file manually!# It will be overwritten by the ALTER SYSTEM command.shared_buffers = '512MB'work_mem = '16MB'maintenance_work_mem = '128MB'effective_cache_size = '1536MB'Règle de priorité : postgresql.auto.conf est lu après postgresql.conf. Si un paramètre existe dans les deux fichiers, c'est la valeur de postgresql.auto.conf qui gagne.
pg_hba.conf : contrôle d'accès (aperçu)
Section intitulée « pg_hba.conf : contrôle d'accès (aperçu) »Ce fichier définit qui peut se connecter, depuis où, et comment s'authentifier. La configuration par défaut sur Debian :
local all postgres peerlocal all all peerhost all all 127.0.0.1/32 scram-sha-256host all all ::1/128 scram-sha-256local replication all peerhost replication all 127.0.0.1/32 scram-sha-256host replication all ::1/128 scram-sha-256Seules les connexions locales (socket Unix) et localhost (127.0.0.1) sont autorisées. Pour ouvrir l'accès réseau, vous devrez modifier à la fois listen_addresses et pg_hba.conf, le détail est dans le guide Sécurisation.
Consulter la configuration active
Section intitulée « Consulter la configuration active »Trois méthodes pour voir la valeur effective d'un paramètre :
SHOW, la plus rapide :
SHOW shared_buffers; shared_buffers---------------- 512MBcurrent_setting(), utilisable dans une requête :
SELECT current_setting('work_mem');pg_settings, la vue complète avec source et contexte :
SELECT name, setting, unit, source, context, pending_restartFROM pg_settingsWHERE name = 'shared_buffers';pg_file_settings, voir ce que les fichiers contiennent (pas forcément appliqué) :
SELECT sourcefile, sourceline, name, setting, appliedFROM pg_file_settingsWHERE name = 'shared_buffers'ORDER BY sourcefile; sourcefile | sourceline | name | setting | applied--------------------------------------------------+------------+----------------+---------+--------- /etc/postgresql/18/main/postgresql.conf | 132 | shared_buffers | 128MB | f /var/lib/postgresql/18/main/postgresql.auto.conf | 3 | shared_buffers | 512MB | tOn voit ici que postgresql.conf contient 128MB (applied = f) mais postgresql.auto.conf impose 512MB (applied = t).
Mémoire : les 4 paramètres à dimensionner
Section intitulée « Mémoire : les 4 paramètres à dimensionner »La mémoire est le levier de performance le plus direct. PostgreSQL distingue la mémoire partagée (commune à toutes les connexions) et la mémoire par opération (allouée individuellement).
shared_buffers : le cache partagé
Section intitulée « shared_buffers : le cache partagé »Le paramètre le plus important. Il définit la taille de la mémoire partagée où PostgreSQL met en cache les pages de données (blocs de 8 Ko) lues depuis le disque.
Valeur par défaut : 128MB, beaucoup trop faible pour un serveur de production.
Règle de dimensionnement : entre 25 % et 40 % de la RAM totale. Sur notre lab avec 2 Go de RAM :
ALTER SYSTEM SET shared_buffers = '512MB';-- Nécessite un RESTARTPourquoi pas 50 % ou plus ? Parce que PostgreSQL s'appuie aussi sur le cache du système d'exploitation (page cache Linux). Si shared_buffers consomme trop de RAM, le page cache rétrécit et les performances globales baissent.
Augmenter shared_buffers pousse souvent à augmenter aussi max_wal_size, pour étaler l'écriture des pages modifiées (dirty pages) sur une période plus longue et éviter des checkpoints trop fréquents.
work_mem : mémoire par opération de tri/hachage
Section intitulée « work_mem : mémoire par opération de tri/hachage »Chaque opération de tri (ORDER BY, DISTINCT, MERGE JOIN) ou de hachage (HASH JOIN, GROUP BY) peut utiliser jusqu'à work_mem de mémoire avant de déborder sur disque (fichiers temporaires).
Valeur par défaut : 4MB
Piège courant : ce n'est pas par connexion, c'est par opération. Une requête complexe avec 5 nœuds de tri peut consommer 5 × work_mem. Et chaque connexion concurrente fait de même.
Calcul prudent : RAM disponible / (max_connections × 2 à 5 opérations). Sur notre lab :
ALTER SYSTEM SET work_mem = '16MB';-- Prend effet après reload (contexte : user)Un work_mem trop faible force des tris sur disque (visible dans EXPLAIN ANALYZE avec Sort Method: external merge). Un work_mem trop élevé avec beaucoup de connexions peut épuiser la RAM.
maintenance_work_mem : pour VACUUM et CREATE INDEX
Section intitulée « maintenance_work_mem : pour VACUUM et CREATE INDEX »Mémoire allouée aux opérations de maintenance : VACUUM, CREATE INDEX, ALTER TABLE ADD FOREIGN KEY. Ces opérations sont ponctuelles mais consomment beaucoup de mémoire pour être efficaces.
Valeur par défaut : 64MB
Règle : 2 à 4 fois work_mem, sans dépasser 1 à 2 Go. Plus la table est grosse, plus un VACUUM bénéficie de mémoire :
ALTER SYSTEM SET maintenance_work_mem = '128MB';-- Prend effet après reload (contexte : user)effective_cache_size : estimation pour le planificateur
Section intitulée « effective_cache_size : estimation pour le planificateur »Ce paramètre n'alloue aucune mémoire. C'est une indication donnée au planificateur de requêtes sur la quantité totale de cache disponible (shared_buffers + page cache OS). Il influence le choix entre un scan séquentiel et un scan d'index.
Valeur par défaut : 4GB
Règle : environ 50 à 75 % de la RAM totale :
ALTER SYSTEM SET effective_cache_size = '1536MB';-- Prend effet après reload (contexte : user)Si la valeur est trop basse, le planificateur favorisera des scans séquentiels même quand un index serait plus rapide.
Tableau : valeurs recommandées selon la RAM disponible
Section intitulée « Tableau : valeurs recommandées selon la RAM disponible »Ces valeurs sont un point de départ pour une charge transactionnelle classique, pas un optimum. La colonne work_mem est donnée en fourchette parce qu'elle dépend de max_connections : prenez la borne basse si vous visez 200 connexions, la borne haute si un PgBouncer ramène la concurrence réelle à quelques dizaines de sessions. Vérifiez que la somme shared_buffers + (work_mem × connexions actives × 2) reste sous la RAM physique, sinon l'OOM killer arbitre à votre place.
| RAM totale | shared_buffers | work_mem | maintenance_work_mem | effective_cache_size |
|---|---|---|---|---|
| 2 Go | 512 Mo | 8–16 Mo | 128 Mo | 1,5 Go |
| 4 Go | 1 Go | 16–32 Mo | 256 Mo | 3 Go |
| 8 Go | 2 Go | 32–64 Mo | 512 Mo | 6 Go |
| 16 Go | 4 Go | 64–128 Mo | 1 Go | 12 Go |
| 32 Go | 8 Go | 128–256 Mo | 2 Go | 24 Go |
Connexions
Section intitulée « Connexions »max_connections : pourquoi ne pas monter à 1 000
Section intitulée « max_connections : pourquoi ne pas monter à 1 000 »Valeur par défaut : 100
Chaque connexion PostgreSQL correspond à un processus système (fork). 100 connexions = 100 processus, chacun avec sa mémoire (work_mem, catalogues système, état de session). Au-delà de 200-300 connexions, les performances chutent à cause du context switching et de la contention mémoire.
SHOW max_connections; max_connections----------------- 100Si votre application a besoin de plus de 100 connexions, la solution n'est pas d'augmenter max_connections à 1 000. La bonne approche est d'introduire un connection pooler comme PgBouncer entre l'application et PostgreSQL.
listen_addresses : écouter au-delà de localhost
Section intitulée « listen_addresses : écouter au-delà de localhost »Par défaut, PostgreSQL n'écoute que sur localhost :
SHOW listen_addresses; listen_addresses------------------ localhostPour autoriser les connexions réseau (depuis une application sur un autre serveur) :
ALTER SYSTEM SET listen_addresses = '*';-- Nécessite un RESTART (contexte : postmaster)'*' signifie « écouter sur toutes les interfaces ». Vous pouvez aussi cibler une IP précise : '192.168.122.60'.
superuser_reserved_connections
Section intitulée « superuser_reserved_connections »Valeur par défaut : 3
Réserve 3 connexions pour les superusers, même quand max_connections est atteint. C'est votre filet de secours pour vous connecter et diagnostiquer quand le serveur est saturé. Ne descendez jamais en dessous de 2.
WAL et checkpoints
Section intitulée « WAL et checkpoints »Le WAL (Write-Ahead Log) est le mécanisme qui garantit la durabilité des données : chaque modification est d'abord écrite dans le journal WAL avant d'être appliquée aux fichiers de données. Les checkpoints sont les moments où PostgreSQL synchronise les pages modifiées en mémoire vers le disque.
wal_level : minimal, replica, logical
Section intitulée « wal_level : minimal, replica, logical »Valeur par défaut : replica
Ce paramètre contrôle la quantité d'informations écrites dans le WAL :
| Niveau | Usage | Conséquence |
|---|---|---|
minimal | Serveur standalone sans sauvegarde PITR | WAL minimal, pas de réplication possible |
replica | Défaut recommandé, réplication physique, pg_basebackup, PITR | Suffisant pour 95 % des cas |
logical | Réplication logique, CDC (Change Data Capture) | WAL plus volumineux |
Gardez replica sauf besoin explicite de réplication logique. Passer de minimal à replica nécessite un restart.
max_wal_size et checkpoint_completion_target
Section intitulée « max_wal_size et checkpoint_completion_target »max_wal_size (défaut : 1GB), volume de WAL accumulé avant de forcer un checkpoint. Plus la valeur est élevée, moins les checkpoints sont fréquents (meilleur débit d'écriture), mais la reprise après crash sera plus longue.
checkpoint_completion_target (défaut : 0.9), fraction du temps entre deux checkpoints pendant laquelle PostgreSQL étale l'écriture des pages sales. 0.9 signifie que l'écriture est répartie sur 90 % de l'intervalle, ce qui réduit les pics d'I/O.
checkpoint_timeout (défaut : 5min), intervalle maximum entre deux checkpoints automatiques.
Pour un serveur de production avec un bon sous-système disque :
ALTER SYSTEM SET max_wal_size = '2GB';ALTER SYSTEM SET checkpoint_completion_target = 0.9; -- déjà la valeur par défaut-- Prend effet après reload (contexte : sighup)Logging utile en exploitation
Section intitulée « Logging utile en exploitation »La configuration par défaut logue les avertissements et erreurs, mais sans collecteur intégré (logging_collector = off) elle reste peu confortable à exploiter en production, pas de rotation automatique, pas de structuration des fichiers, et un risque de logs perdus quand plusieurs processus écrivent en concurrence sur stderr. Voici une configuration réaliste pour la production.
Activer le collecteur de logs
Section intitulée « Activer le collecteur de logs »Sans logging_collector, PostgreSQL écrit sur stderr et c'est le gestionnaire de service qui décide du sort des lignes. Le collecteur est un processus dédié qui capte cette sortie et l'écrit dans des fichiers datés, avec rotation. Les trois paramètres ci-dessous vont ensemble : log_directory est relatif au data directory quand il ne commence pas par /, et le motif de log_filename détermine la granularité de la rotation, ici un fichier par jour.
ALTER SYSTEM SET logging_collector = 'on';ALTER SYSTEM SET log_directory = 'log';ALTER SYSTEM SET log_filename = 'postgresql-%Y-%m-%d.log';-- logging_collector nécessite un RESTART (contexte : postmaster)Les logs sont écrits dans $PGDATA/log/, soit /var/lib/postgresql/18/main/log/ sur Debian :
-rw------- 1 postgres postgres 2885 Apr 13 10:01 postgresql-2026-04-13.loglog_statement : tracer les requêtes DDL
Section intitulée « log_statement : tracer les requêtes DDL »log_statement trace des requêtes selon leur nature, sans tenir compte de leur durée. C'est ce qui le distingue de log_min_duration_statement : l'un répond à « qui a modifié le schéma », l'autre à « qu'est-ce qui est lent ». Le niveau ddl est le bon compromis en production, il capture les CREATE, ALTER et DROP pour un volume de logs négligeable. Deux limites à connaître sur le niveau all : il fait exploser le volume de logs sur une base active, et il ne rattrape pas tout, les requêtes contenant une erreur de syntaxe ne sont jamais loguées, même en all, parce que le message est émis après l'analyse syntaxique.
| Valeur | Ce qui est logué |
|---|---|
none | Rien (défaut) |
ddl | CREATE, ALTER, DROP, recommandé en production |
mod | ddl + INSERT, UPDATE, DELETE |
all | Toutes les requêtes, uniquement pour le debug |
ALTER SYSTEM SET log_statement = 'ddl';log_min_duration_statement : trouver les requêtes lentes
Section intitulée « log_min_duration_statement : trouver les requêtes lentes »Le paramètre le plus utile en exploitation. Il trace toutes les requêtes dont la durée dépasse le seuil :
ALTER SYSTEM SET log_min_duration_statement = 500; -- en millisecondesAvec 500, toute requête prenant plus d'une demi-seconde apparaît dans les logs avec sa durée exacte et son texte SQL complet. C'est le premier outil de diagnostic avant pg_stat_statements.
log_connections, log_disconnections, log_lock_waits
Section intitulée « log_connections, log_disconnections, log_lock_waits »Ces trois paramètres répondent à des questions d'exploitation que les logs de requêtes ne couvrent pas : d'où viennent les sessions, combien de temps elles vivent, et lesquelles se bloquent mutuellement. Le couple connexion / déconnexion est ce qui permet de repérer une application qui ouvre et referme une session par requête, un motif qui sature un serveur bien avant que les requêtes ne deviennent lentes. log_lock_waits est le seul des trois à produire un volume négligeable tout en pointant directement une contention de verrous, activez-le sans hésiter.
ALTER SYSTEM SET log_connections = 'all';ALTER SYSTEM SET log_disconnections = 'on';ALTER SYSTEM SET log_lock_waits = 'on';log_connections: trace les connexions entrantes. En PostgreSQL 18, ce paramètre accepte des options granulaires :receipt,authentication,authorization,setup_durations, ouall. La valeuronreste acceptée pour compatibilité mais n'active qu'un sous-ensemble. Préférez'all'pour une visibilité complète.log_disconnections: trace chaque déconnexion avec la durée de sessionlog_lock_waits: trace les requêtes qui attendent un verrou plus longtemps quedeadlock_timeout(1 seconde par défaut)
Exemple de ce que les logs montrent avec cette configuration :
2026-04-13 10:01:20.273 [6287] postgres@postgres LOG: connection authorized: user=postgres database=postgres application_name=psql2026-04-13 10:01:20.275 [6287] postgres@postgres LOG: disconnection: session time: 0:00:00.003 user=postgres database=postgres host=[local]log_line_prefix : structurer les lignes de log
Section intitulée « log_line_prefix : structurer les lignes de log »Le préfixe détermine les métadonnées ajoutées à chaque ligne de log :
ALTER SYSTEM SET log_line_prefix = '%m [%p] %q%u@%d/%a ';| Placeholder | Signification |
|---|---|
%m | Horodatage avec millisecondes |
%p | PID du processus |
%q | Rien si la session n'est pas liée à un client (processus interne) |
%u | Nom du rôle |
%d | Nom de la base de données |
%a | Nom de l'application (application_name) |
Résultat dans les logs : 2026-04-13 10:01:20.273 [6287] postgres@postgres/psql LOG: ...
L'ajout de %a permet de distinguer immédiatement les requêtes venant de votre application, de PgBouncer, d'un script cron ou de psql.
log_lock_failures (nouveau PostgreSQL 18)
Section intitulée « log_lock_failures (nouveau PostgreSQL 18) »PostgreSQL 18 ajoute log_lock_failures, mais sa portée est encore limitée : la documentation indique qu'il couvre actuellement les échecs de verrouillage liés à NOWAIT (par exemple SELECT ... FOR UPDATE NOWAIT qui échoue parce que la ligne est déjà verrouillée). C'est complémentaire de log_lock_waits qui ne trace que les attentes au-delà de deadlock_timeout.
ALTER SYSTEM SET log_lock_failures = 'on';Configuration de logging recommandée (récapitulatif)
Section intitulée « Configuration de logging recommandée (récapitulatif) »Ce bloc rassemble les réglages précédents dans l'ordre où il faut les appliquer. La séparation entre les deux groupes compte : seul logging_collector impose un restart, tout le reste passe par un simple reload. Si vous ne pouvez pas redémarrer immédiatement, appliquez le second groupe tout de suite, il produit déjà l'essentiel du diagnostic. Deux paramètres sont propres à PostgreSQL 18 et provoqueront une erreur sur une version antérieure : log_lock_failures, et la valeur all de log_connections.
-- Collecteur (RESTART obligatoire)ALTER SYSTEM SET logging_collector = 'on';ALTER SYSTEM SET log_directory = 'log';ALTER SYSTEM SET log_filename = 'postgresql-%Y-%m-%d.log';
-- Contenu des logs (RELOAD suffit)ALTER SYSTEM SET log_statement = 'ddl';ALTER SYSTEM SET log_min_duration_statement = 500;ALTER SYSTEM SET log_connections = 'all';ALTER SYSTEM SET log_disconnections = 'on';ALTER SYSTEM SET log_lock_waits = 'on';ALTER SYSTEM SET log_lock_failures = 'on';ALTER SYSTEM SET log_line_prefix = '%m [%p] %q%u@%d/%a ';Autovacuum : laisser faire mais surveiller
Section intitulée « Autovacuum : laisser faire mais surveiller »Pourquoi VACUUM est vital
Section intitulée « Pourquoi VACUUM est vital »PostgreSQL utilise le modèle MVCC (Multi-Version Concurrency Control) : quand vous faites un UPDATE, l'ancienne version de la ligne n'est pas supprimée, elle est marquée comme "morte" ("dead tuple"). C'est ce qui permet aux transactions concurrentes de lire les anciennes valeurs sans bloquer.
Le problème : ces lignes mortes accumulent du bloat (espace gaspillé). Sans nettoyage régulier :
- Les tables grossissent inutilement sur disque
- Les scans deviennent plus lents (plus de pages à parcourir)
- Le risque de transaction ID wraparound augmente, un scénario catastrophe où PostgreSQL refuse toute nouvelle écriture pour protéger l'intégrité des données
L'autovacuum est le processus automatique qui nettoie ces lignes mortes. Il est activé par défaut et c'est rarement une bonne idée de le désactiver.
Paramètres clés de l'autovacuum
Section intitulée « Paramètres clés de l'autovacuum »Les valeurs par défaut conviennent à la majorité des bases, et la première chose à comprendre est laquelle de ces lignes vous devrez toucher un jour. Ce sont presque toujours les deux dernières : autovacuum_vacuum_scale_factor, parce qu'un pourcentage fixe devient absurde sur une grosse table, et autovacuum_vacuum_cost_delay, parce que le nettoyage est volontairement bridé pour ne pas saturer les disques. Ces deux paramètres se règlent aussi table par table avec ALTER TABLE ... SET (autovacuum_vacuum_scale_factor = 0.01), ce qui est presque toujours préférable à un changement global.
| Paramètre | Défaut | Description |
|---|---|---|
autovacuum | on | Active le processus. Ne le désactivez pas. |
autovacuum_naptime | 1min | Fréquence de vérification des tables à nettoyer |
autovacuum_max_workers | 3 | Nombre de workers parallèles |
autovacuum_vacuum_threshold | 50 | Nombre minimum de lignes mortes avant déclenchement |
autovacuum_vacuum_scale_factor | 0.2 | Fraction de la table (20 %) qui doit être "morte" |
autovacuum_vacuum_cost_delay | 2ms | Pause entre les cycles I/O (pour limiter l'impact) |
Formule de déclenchement : l'autovacuum se déclenche quand n_dead_tup > threshold + scale_factor × n_live_tup. Pour une table de 10 000 lignes : 50 + 0.2 × 10 000 = 2050 lignes mortes avant déclenchement.
autovacuum_vacuum_max_threshold (nouveau PostgreSQL 18)
Section intitulée « autovacuum_vacuum_max_threshold (nouveau PostgreSQL 18) »PostgreSQL 18 ajoute autovacuum_vacuum_max_threshold (défaut : 100 000 000). Il fixe un plafond absolu au nombre de lignes modifiées avant de forcer un VACUUM, indépendamment du scale_factor. Sur les très grosses tables (des milliards de lignes), scale_factor seul pouvait retarder le VACUUM trop longtemps.
Comment savoir si l'autovacuum est en retard
Section intitulée « Comment savoir si l'autovacuum est en retard »La vue pg_stat_user_tables est le seul endroit qui dit si le nettoyage suit le rythme des écritures. Deux colonnes se lisent ensemble et jamais séparément : n_dead_tup donne le nombre de lignes mortes en attente, last_autovacuum donne la date du dernier passage. Un n_dead_tup élevé n'est un problème que si last_autovacuum est ancien, sinon c'est le compteur normal d'une table qui vient d'encaisser des écritures. Triez par n_dead_tup décroissant pour faire remonter les tables à traiter en premier.
SELECT schemaname, relname, n_dead_tup, n_mod_since_analyze, last_autovacuum, last_autoanalyzeFROM pg_stat_user_tablesORDER BY n_dead_tup DESC; schemaname | relname | n_dead_tup | n_mod_since_analyze | last_autovacuum | last_autoanalyze------------+-----------+------------+---------------------+-----------------+------------------ app | clients | 2 | 7 | | app | commandes | 0 | 5 | |Signaux d'alerte :
n_dead_tupélevé etlast_autovacuumancien (ou NULL) → l'autovacuum ne passe pas assez souventn_mod_since_analyzeélevé → les statistiques du planificateur sont obsolètes (ANALYZE nécessaire)- Tables qui grossissent sur disque alors que le nombre de lignes vivantes ne change pas → bloat
Recharger sans redémarrer
Section intitulée « Recharger sans redémarrer »Trois méthodes de rechargement
Section intitulée « Trois méthodes de rechargement »Les trois commandes ci-dessous font exactement la même chose : envoyer le signal SIGHUP au processus principal, qui relit les fichiers de configuration et propage les valeurs à ses processus enfants. Aucune ne coupe les sessions en cours. Le choix dépend seulement de l'endroit d'où vous travaillez : pg_reload_conf() depuis psql est le plus direct et retourne t en cas de succès, les deux autres supposent un accès shell. Un point commun à retenir : aucune ne signale qu'un paramètre est resté sans effet, d'où la vérification de pending_restart décrite plus bas.
Depuis psql (recommandé) :
SELECT pg_reload_conf(); pg_reload_conf---------------- tDepuis le shell :
sudo systemctl reload postgresql@18-mainAvec l'outil de gestion de clusters fourni par les paquets Debian/Ubuntu :
sudo -u postgres pg_ctlcluster 18 main reloadParamètres qui exigent un restart
Section intitulée « Paramètres qui exigent un restart »Certains paramètres ont le contexte postmaster : ils ne prennent effet qu'au prochain démarrage du service. Les plus courants :
| Paramètre | Impact du changement |
|---|---|
shared_buffers | Taille de la mémoire partagée |
max_connections | Limite de connexions simultanées |
listen_addresses | Interfaces réseau écoutées |
wal_level | Niveau de détail du WAL |
logging_collector | Activation du collecteur de logs |
port | Port TCP |
Tous les autres paramètres couverts dans ce guide (mémoire par opération, logging, autovacuum) prennent effet avec un simple reload.
Vérifier les paramètres en attente
Section intitulée « Vérifier les paramètres en attente »Après un ALTER SYSTEM suivi d'un reload, vérifiez si des paramètres attendent encore un restart :
SELECT name, setting, pending_restartFROM pg_settingsWHERE pending_restart = true;Si la requête retourne des lignes, un systemctl restart postgresql@18-main est nécessaire pour les appliquer.
Workflow complet de modification
Section intitulée « Workflow complet de modification »Cette séquence de quatre gestes est celle à appliquer pour chaque paramètre modifié. L'étape 3 mérite une précision : SHOW doit être exécuté dans une nouvelle session, car les paramètres de contexte user conservent leur ancienne valeur dans les sessions déjà ouvertes. Si vous vérifiez depuis la session qui a lancé l'ALTER SYSTEM, vous lirez l'ancienne valeur et conclurez à tort que le rechargement a échoué.
-
Modifier le paramètre avec
ALTER SYSTEM:ALTER SYSTEM SET work_mem = '32MB'; -
Recharger la configuration :
SELECT pg_reload_conf(); -
Vérifier dans une nouvelle session :
SHOW work_mem; -
Si
pending_restart = true: redémarrer le serviceFenêtre de terminal sudo systemctl restart postgresql@18-main
Dépannage
Section intitulée « Dépannage »Presque tous les problèmes de configuration PostgreSQL se ramènent à deux causes : un paramètre de contexte postmaster rechargé alors qu'il exige un restart, ou une valeur écrasée par postgresql.auto.conf. Avant de chercher plus loin, exécutez SELECT * FROM pg_settings WHERE name = '<param>' et lisez les colonnes source, context et pending_restart : elles répondent à elles seules aux quatre premières lignes du tableau.
| Symptôme | Cause probable | Solution |
|---|---|---|
SHOW shared_buffers retourne l'ancienne valeur après reload | Contexte postmaster | systemctl restart postgresql@18-main |
Logs vides malgré log_statement = 'all' | logging_collector = off | Activer + restart |
ALTER SYSTEM ignoré | postgresql.conf rechargé depuis un outil de CONFIG MANAGEMENT qui ne touche pas auto.conf | Vérifier pg_file_settings, la valeur auto.conf a priorité |
| Mémoire saturée (OOM killer) | shared_buffers + work_mem × connexions > RAM | Réduire work_mem ou max_connections |
| Autovacuum ne passe jamais | Seuil trop haut pour les petites tables | Baisser autovacuum_vacuum_threshold ou le scale_factor |
pending_restart reste à true | Le service n'a pas été restart, seulement reload | systemctl restart postgresql@18-main |
À retenir
Section intitulée « À retenir »- La configuration par défaut est conservatrice, adaptez toujours
shared_buffers,work_memet le logging à votre serveur. shared_buffers: 25 à 40 % de la RAM, c'est le paramètre le plus impactant sur les performances.work_memest par opération, pas par connexion, attention à ne pas dépasser la RAM disponible avec beaucoup de connexions.effective_cache_sizen'alloue rien, c'est une indication pour le planificateur (50-75 % de la RAM).max_connectionsau-delà de 200 : pensez PgBouncer plutôt qu'augmenter la valeur.- Activez
log_min_duration_statementdès le premier jour, c'est le premier outil pour trouver les requêtes lentes. - Ne désactivez jamais l'autovacuum, le risque de wraparound est un scénario catastrophe.
postgresql.auto.confa priorité surpostgresql.conf, choisissez une seule méthode de gestion.- Vérifiez
pending_restartaprès chaque modification, certains paramètres exigent un restart complet.