📄8) Exemple de gabarit
L’idée : donner un point de départ réaliste, déjà cohérent (RAM, WAL, autovacuum, logs), que tu adapteras ensuite avec les recettes de la section 7.
Petit serveur / VM (≤ 8 Go)
Dev, staging, petites applis. On évite les valeurs trop hautes qui tuent le système.
Serveur standard (32–64 Go)
Cas le plus courant : OLTP/Mixte, appli web, ERP, CRM.
Gros serveur / OLAP / 128+ Go
Scans, BI, parallélisme, WAL élevé.
Conteneur / K8s / Cloud managé
Logs en STDOUT, mémoire volatile, pas de chemin disque figé.
Cas typique : machine 2–4 vCPU, 4 à 8 Go de RAM, application web mono-tenant, quelques batchs. On ne peut pas se permettre 20 Go de buffers : on reste sage.
- max_connections = 80–120 (le reste dans PgBouncer)
- shared_buffers ≈ 25% mais pas plus que 2 Go
- work_mem petit (4–8 MB) car peu de RAM
- WAL pas trop gros (4–8 GB) sinon ça mange le disque
# ========================= # PostgreSQL small / VM # Point de départ # ========================= listen_addresses = '*' max_connections = 100 shared_buffers = 2GB effective_cache_size = 4GB work_mem = 8MB maintenance_work_mem = 256MB # WAL / Checkpoints wal_level = replica max_wal_size = 8GB checkpoint_timeout = 15min checkpoint_completion_target = 0.9 # Autovacuum par défaut + log_autovacuum_min_duration = 1000 # Temps d'exécution statement_timeout = 3000 # Planner (SSD) random_page_cost = 1.1 effective_io_concurrency = 32 # Journaux logging_collector = on log_line_prefix = '%m [%p] %u@%d %r ' log_min_duration_statement = 500
Notes d’exploitation
- Surveiller les fichiers temporaires : si > 100 MB souvent → augmenter
work_memà 16 MB. - Si c’est du dev → on peut baisser
wal_levelàminimal. - Mettre PgBouncer devant si plusieurs applis y accèdent.
- Mettre en cron un
pg_dumpquotidien (machines petites = pas de réplica).
Serveur physique ou VM costaude : 8 vCPU+, 32 à 64 Go RAM. C’est souvent TON cas. On peut se permettre 8–16 Go de buffers, WAL plus large, autovacuum un peu plus verbeux.
- max_connections = 150–250 (si PgBouncer devant)
- shared_buffers = 8–16 GB
- effective_cache_size = 75–80% RAM → 24–48 GB
- max_wal_size = 16–32 GB
- checkpoint_timeout = 20–30 min
# ========================= # PostgreSQL standard 32–64GB # Point de départ IDEO-Lab # ========================= listen_addresses = '*' max_connections = 200 shared_buffers = 12GB effective_cache_size = 36GB work_mem = 32MB maintenance_work_mem = 1GB # WAL / Checkpoints wal_level = replica max_wal_size = 32GB checkpoint_timeout = 25min checkpoint_completion_target = 0.9 # Write synchronous_commit = on wal_compression = on # Planner / I/O random_page_cost = 1.1 effective_io_concurrency = 64 # Autovacuum & logs log_autovacuum_min_duration = 1000 log_line_prefix = '%m [%p] %u@%d %r ' log_min_duration_statement = 500 # Parallelism (modéré) max_worker_processes = 16 max_parallel_workers = 8 max_parallel_workers_per_gather = 2
Variantes rapides
Variante OLTP : baisser work_mem à 8–16 MB, mettre synchronous_commit=off, garder les mêmes buffers.
# patch OLTP work_mem = 16MB synchronous_commit = off statement_timeout = 2000
Variante OLAP : monter work_mem à 128–256 MB + max_parallel_workers_per_gather = 3
# patch OLAP work_mem = 256MB max_parallel_workers_per_gather = 3 max_parallel_workers = 12
Ici on parle de nœuds analytics, grosses RAM (128–256 Go), stockage NVMe/ceph rapide, requêtes longues. On évite quand même de mettre 60% de RAM en shared_buffers : on laisse l’OS gérer.
- shared_buffers = 15–20% max, même avec 256 Go
- effective_cache_size = 75–85%
- work_mem très haut mais souvent par session ETL
- parallélisme 3–4 workers
- JIT on mais seuils élevés
# ========================= # PostgreSQL Big / OLAP # ========================= listen_addresses = '*' max_connections = 60 shared_buffers = 32GB # 15–20% d'un 160–256GB effective_cache_size = 160GB work_mem = 256MB # à affiner par session maintenance_work_mem = 4GB wal_level = replica max_wal_size = 64GB checkpoint_timeout = 30min checkpoint_completion_target = 0.9 # Parallélisme max_worker_processes = 32 max_parallel_workers = 16 max_parallel_workers_per_gather = 4 # JIT jit = on jit_above_cost = 100000 jit_inline_above_cost = 200000 jit_optimize_above_cost = 500000 # I/O random_page_cost = 1.1 effective_io_concurrency = 256 log_line_prefix = '%m [%p] %u@%d %r ' log_min_duration_statement = 1000
Points de vigilance
- Surveiller les temp files → si > quelques Go, augmenter encore
work_memmais plutôt au niveau SESSION. - Partitionner les tables volumineuses → sinon VACUUM/ANALYZE seront lents.
- Prévoir un plan de réindex (pg_repack) si beaucoup d’updates sur gros index.
En conteneur on évite d’écrire dans des chemins locaux éphémères, on laisse souvent la plateforme gérer les logs. On baisse les connexions (pods éphémères) et on met un pooler à l’extérieur.
- max_connections = 50–80
- logging_collector = off (stdout)
- checkpoint_timeout + WAL pas trop gros (pods qui bougent)
# ========================= # PostgreSQL in container # ========================= listen_addresses = '*' max_connections = 60 shared_buffers = 2GB effective_cache_size = 4GB work_mem = 8MB maintenance_work_mem = 256MB wal_level = replica max_wal_size = 4GB checkpoint_timeout = 10min checkpoint_completion_target = 0.9 # Logs vers stdout logging_collector = off log_statement = 'none' log_min_duration_statement = 750 log_line_prefix = '%m [%p] %u@%d %r ' random_page_cost = 1.1
Notes cloud / k8s
- Si c’est un service managé (RDS, AlloyDB, etc.) : ne pas forcer les paramètres gérés par le provider.
- Exporter les métriques vers Prometheus/Grafana (cf. ta section 6).
- Monter un PgBouncer sidecar ou externe pour absorber les connexions courtes.
