Aide-mémoire3 min de lecture · Mis à jour le 29 sept. 2026
Optimisation de requêtes SQL — aide-mémoire EXPLAIN
Lire un plan d'exécution, choisir le bon index et éviter les anti-patterns qui rendent les requêtes lentes.
- #sql
- #performance
Lire un plan
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE customer_id = 42;
| Nœud | Signification |
|---|---|
| Seq Scan | lecture complète de la table |
| Index Scan | parcours d'index puis accès à la table |
| Index Only Scan | réponse depuis l'index seul (visibility map à jour) |
| Bitmap Heap Scan | combinaison d'index, bonne pour sélectivité moyenne |
| Nested Loop / Hash Join / Merge Join | stratégies de jointure |
Comparez rows estimées et rows réelles : un écart ×10 signale des statistiques obsolètes (ANALYZE table).
Choisir l'index
- Colonnes en égalité d'abord, puis la colonne de tri ou de plage :
CREATE INDEX ON orders (customer_id, created_at DESC); - Index partiel pour les sous-ensembles fréquents :
WHERE status = 'pending'. - Index couvrant :
INCLUDE (total)pour permettre l'Index Only Scan. - En production :
CREATE INDEX CONCURRENTLY(pas de verrou bloquant l'écriture).
Anti-patterns
- Fonction sur la colonne indexée :
WHERE lower(email) = …→ créer un index d'expression. LIKE '%motif'→ index trigram (pg_trgm).SELECT *sur des tables larges.- Conversion implicite de type (
WHERE id = '42'sur une colonne numérique dans certains SGBD). - Requêtes N+1 depuis l'ORM.
OFFSETélevé pour paginer → pagination par clé (WHERE id > :dernier).
Trouver les requêtes coûteuses
SELECT calls, round(mean_exec_time::numeric,2) AS ms_moy,
round(total_exec_time::numeric) AS ms_total, query
FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 10;
Optimisez d'abord ce qui pèse le plus en temps total, pas la requête la plus lente isolée.