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œudSignification
Seq Scanlecture complète de la table
Index Scanparcours d'index puis accès à la table
Index Only Scanréponse depuis l'index seul (visibility map à jour)
Bitmap Heap Scancombinaison d'index, bonne pour sélectivité moyenne
Nested Loop / Hash Join / Merge Joinstraté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

  1. Fonction sur la colonne indexée : WHERE lower(email) = … → créer un index d'expression.
  2. LIKE '%motif' → index trigram (pg_trgm).
  3. SELECT * sur des tables larges.
  4. Conversion implicite de type (WHERE id = '42' sur une colonne numérique dans certains SGBD).
  5. Requêtes N+1 depuis l'ORM.
  6. 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.

Autres labs de cette technologie