Diagnostiquer une requête lente
AvancéUne méthode en cinq étapes évite de deviner : mesurer, comprendre, corriger, vérifier.
La démarche#
- Reproduire avec les vrais paramètres et un volume réaliste (
\timing,EXPLAIN (ANALYZE, BUFFERS)). - Comparer estimations et réalité : un grand écart
rows=/actual rows=indique des statistiques faussées (ANALYZE, statistiques étendues). - Trouver le nœud coûteux : le plus grand
actual time, en tenant compte deloops. - Corriger avec le levier adapté (tableau ci-dessous).
- Vérifier : refaire l'
EXPLAINet surveillerpg_stat_statementsaprès déploiement.
Symptôme → piste#
| Symptôme dans le plan | Cause probable | Piste |
|---|---|---|
Seq Scan sur grosse table, peu de lignes ramenées | Index manquant ou inutilisable | Créer l'index ; éviter les fonctions sur la colonne |
Rows Removed by Filter énorme | Filtre appliqué après lecture | Index (éventuellement partiel ou composite) |
| Estimations très fausses | Statistiques obsolètes ou colonnes corrélées | ANALYZE, CREATE STATISTICS |
Sort Method: external merge | work_mem trop bas pour ce tri | Index qui fournit l'ordre, ou augmenter work_mem pour la session |
Nested Loop avec loops énorme | Mauvais choix de jointure, estimation basse | Statistiques, index sur la clé jointe |
Beaucoup de shared read | Données non cachées | Index plus sélectif, plus de RAM, réduire les colonnes lues |
| Milliers de requêtes très rapides | Problème N+1 | Regrouper (JOIN, = ANY($1)) |
| Lenteur intermittente | Verrous, autovacuum, checkpoint, plan différent selon les paramètres | pg_stat_activity, log_lock_waits, auto_explain |
Piège : optimiser en local sur 1 000 lignes n'a aucun sens : le planificateur choisit d'autres plans à 10 millions de lignes. Testez sur un jeu de données de taille et de distribution proches de la production.