SQL Pratique
EXPLAIN en SQL : analyser et optimiser vos requêtes
9 min de lecture

EXPLAIN en SQL : analyser et optimiser vos requêtes

Découvrez comment utiliser EXPLAIN et EXPLAIN ANALYZE en SQL pour diagnostiquer vos requêtes lentes et gagner en performance. Guide pratique avec exemples.

Avatar de Thomas LeroyThomas Leroy

Comprendre pourquoi une requête SQL est lente commence toujours par la même commande : EXPLAIN. Cet outil intégré à la quasi-totalité des SGBD modernes vous révèle exactement comment le moteur de base de données prévoit d'exécuter votre requête, avant même qu'elle ne tourne. En entretien technique comme en production, savoir lire un plan d'exécution est une compétence qui sépare les développeurs data ordinaires des profils vraiment solides.

Dans cet article, vous apprendrez à utiliser EXPLAIN (et sa variante EXPLAIN ANALYZE) pour identifier les goulots d'étranglement, repérer les scans de table inutiles, et comprendre pourquoi l'optimiseur choisit — ou évite — un index. Des exemples concrets en PostgreSQL et MySQL illustrent chaque concept.

📌 Ce qu'il faut retenir

  • EXPLAIN affiche le plan d'exécution estimé sans exécuter la requête
  • EXPLAIN ANALYZE exécute réellement la requête et compare estimations vs réalité
  • Un Sequential Scan sur une grande table est souvent le signe d'un index manquant
  • Lire le plan de bas en haut : le nœud le plus indenté s'exécute en premier

Ce que fait réellement EXPLAIN

Quand vous préfixez une requête avec EXPLAIN, le moteur SQL ne l'exécute pas. Il demande à l'optimiseur de produire le plan d'exécution qu'il utiliserait, puis l'affiche sous forme d'arbre d'opérations. Chaque nœud correspond à une étape : lecture d'une table, application d'un filtre, fusion de deux ensembles via une jointure, etc.

L'optimiseur s'appuie sur des statistiques internes (distribution des valeurs, cardinalité des tables, présence d'index) pour choisir le plan le moins coûteux. Ce coût est une estimation abstraite, pas des millisecondes — mais il vous indique quelles opérations sont jugées "chères" par le moteur.

En PostgreSQL, la syntaxe de base est simple :

EXPLAIN SELECT * FROM commandes WHERE client_id = 42;

La sortie ressemble à ceci :

Seq Scan on commandes  (cost=0.00..4523.00 rows=18 width=96)
  Filter: (client_id = 42)

Ici, le moteur prévoit un Sequential Scan (lecture ligne par ligne) de toute la table. Si commandes contient des millions de lignes, c'est un problème évident.

EXPLAIN ANALYZE : la version avec données réelles

EXPLAIN ANALYZE va plus loin : il exécute la requête et ajoute les temps réels à côté des estimations. C'est indispensable pour détecter les cas où l'optimiseur sous-estime ou surévalue la cardinalité d'un résultat.

EXPLAIN ANALYZE SELECT * FROM commandes WHERE client_id = 42;

Sortie typique :

Seq Scan on commandes  (cost=0.00..4523.00 rows=18 width=96)
                       (actual time=0.043..312.8 rows=2341 loops=1)
  Filter: (client_id = 42)
  Rows Removed by Filter: 198432
Planning Time: 0.12 ms
Execution Time: 315.3 ms

Deux signaux d'alarme apparaissent ici. D'abord, l'optimiseur estimait 18 lignes retournées, mais 2 341 ont été trouvées : les statistiques sont obsolètes. Ensuite, 198 432 lignes ont été filtrées après lecture — autant de travail inutile qui justifie un index sur client_id.

⚠️ Attention

Sur une table de production, EXPLAIN ANALYZE exécute réellement la requête. Évitez de l'utiliser sur des requêtes DELETE ou UPDATE sans les entourer d'une transaction que vous annulez avec ROLLBACK.

Lire un plan d'exécution : les nœuds essentiels

Un plan d'exécution est un arbre. La règle de lecture est constante : commencez par le nœud le plus indenté (le plus profond), car c'est lui qui s'exécute en premier. Les résultats remontent ensuite vers le nœud parent.

Voici les nœuds que vous rencontrerez le plus souvent :

Nœud Description Signal
Seq Scan Lecture séquentielle de toute la table ⚠️ Coûteux sur grandes tables sans index
Index Scan Utilisation d'un index B-tree pour localiser les lignes ✅ Efficace pour sélectivité élevée
Index Only Scan Réponse entière fournie par l'index (covering index) ✅ Optimal, évite l'accès à la table
Bitmap Heap Scan Combine plusieurs index pour filtrer 🔄 Bon compromis sur cardinalité moyenne
Hash Join Jointure via table de hachage en mémoire ✅ Efficace sur grandes tables sans index de jointure
Nested Loop Boucle imbriquée pour chaque ligne du jeu externe ⚠️ Mauvais si le jeu interne est grand
Merge Join Fusion de 2 ensembles triés ✅ Très efficace si les données sont déjà triées
Sort Tri explicite (ORDER BY, DISTINCT, Merge Join) ⚠️ Coûteux si trop de lignes à trier

Comment EXPLAIN guide la création d'index

L'un des usages les plus directs d'EXPLAIN est de confirmer qu'un index est bien utilisé — ou de comprendre pourquoi il ne l'est pas. Prenons un exemple concret.

Après avoir ajouté un index sur client_id :

CREATE INDEX idx_commandes_client ON commandes(client_id);
EXPLAIN SELECT * FROM commandes WHERE client_id = 42;

Le plan devient :

Index Scan using idx_commandes_client on commandes
  (cost=0.43..12.7 rows=18 width=96)
  Index Cond: (client_id = 42)

Le coût est passé de 4 523 à 12,7 — soit une réduction de 99 %. C'est le type de démonstration concrète attendu lors d'un entretien sur la performance et l'optimisation SQL.

Il arrive cependant que l'optimiseur ignore un index existant. Cela se produit notamment quand :

  • La table est trop petite (un Seq Scan est plus rapide)
  • La colonne a une faible sélectivité (ex. une colonne booléenne)
  • Les statistiques sont obsolètes (relancez ANALYZE en PostgreSQL)
  • La requête applique une fonction sur la colonne indexée : WHERE UPPER(nom) = 'MARTIN' ne peut pas utiliser un index sur nom

💡 Bon à savoir

Si vous suspectez des statistiques obsolètes, lancez ANALYZE nom_table en PostgreSQL ou ANALYZE TABLE nom_table en MySQL. L'optimiseur recalculera les distributions de valeurs et ses estimations de cardinalité seront bien plus précises.

EXPLAIN sur les requêtes avec jointures

Les jointures sont souvent le point de départ des problèmes de performance. EXPLAIN vous montre exactement quelle stratégie le moteur choisit pour assembler deux tables. Considérez cette requête :

EXPLAIN ANALYZE
SELECT c.nom, COUNT(o.id) AS nb_commandes
FROM clients c
LEFT JOIN commandes o ON c.id = o.client_id
GROUP BY c.nom;

Si le plan révèle un Hash Join avec un grand nombre de lignes côté commandes et un Sort final pour le GROUP BY, vous avez 2 pistes d'optimisation immédiates : un index sur commandes.client_id (pour éviter un full scan) et éventuellement un index sur clients.nom si le tri devient coûteux.

Pour aller plus loin sur les jointures, consultez notre guide INNER JOIN vs LEFT JOIN qui détaille la logique de chaque type et ses implications sur les performances.

Différences entre PostgreSQL, MySQL et SQL Server

La commande EXPLAIN existe dans les 3 grands SGBD, mais sa syntaxe et son niveau de détail varient.

En MySQL, EXPLAIN renvoie un tableau avec des colonnes comme type, key, rows et Extra. La valeur ALL dans la colonne type équivaut à un Sequential Scan : c'est le pire cas. La colonne Extra avec Using filesort ou Using temporary signale des opérations coûteuses.

En SQL Server, l'équivalent s'appelle SET SHOWPLAN_TEXT ON ou, graphiquement, "Afficher le plan d'exécution estimé" dans SSMS. Le plan est rendu sous forme de graphe avec des pourcentages de coût relatif par nœud.

En PostgreSQL, EXPLAIN (FORMAT JSON) ou EXPLAIN (FORMAT TEXT, BUFFERS, ANALYZE) donne accès aux informations les plus riches, notamment le nombre de blocs lus depuis le disque vs depuis le cache (shared hit vs read).

EXPLAIN en entretien technique : ce qu'on attend de vous

En entretien data, EXPLAIN apparaît souvent dans des questions du type : "Cette requête est lente, comment diagnostiqueriez-vous le problème ?". Les recruteurs attendent une réponse structurée en 3 temps.

D'abord, isoler la requête et lancer EXPLAIN ANALYZE pour obtenir le plan réel. Ensuite, identifier le nœud coûteux : Sequential Scan inattendu, Nested Loop sur un grand jeu, Sort sans index. Enfin, proposer une action corrective : création d'index, réécriture de la requête, mise à jour des statistiques.

Montrer que vous savez lire un plan d'exécution prouve que vous comprenez ce qui se passe à l'intérieur du moteur — bien au-delà de la syntaxe SQL de surface. C'est exactement ce que valorisent les équipes data engineering et analytics dans les profils qu'elles recrutent.


Questions fréquentes

Quelle est la différence entre EXPLAIN et EXPLAIN ANALYZE ?

EXPLAIN génère le plan d'exécution estimé sans exécuter la requête. EXPLAIN ANALYZE exécute réellement la requête et affiche en parallèle les estimations de l'optimiseur et les mesures réelles (temps, nombre de lignes). C'est EXPLAIN ANALYZE qui permet de détecter les écarts entre prévisions et réalité.

Pourquoi l'optimiseur n'utilise-t-il pas mon index ?

Plusieurs raisons sont possibles : la table est petite (un Seq Scan est plus rapide), la colonne a peu de valeurs distinctes (faible sélectivité), les statistiques sont obsolètes, ou la requête applique une transformation sur la colonne (ex. LOWER(email)) qui empêche l'utilisation de l'index standard. Créez un index fonctionnel dans ce dernier cas.

EXPLAIN ANALYZE modifie-t-il les données ?

Non, sur une SELECT. Mais sur une UPDATE, DELETE ou INSERT, la requête est réellement exécutée. Enveloppez-la dans une transaction : BEGIN; EXPLAIN ANALYZE UPDATE ...; ROLLBACK; pour annuler les modifications après diagnostic.

Que signifie le coût affiché par EXPLAIN ?

Le coût est une unité abstraite interne à l'optimiseur (en PostgreSQL, 1 unité ≈ lecture séquentielle d'une page disque). Il ne correspond pas à des millisecondes. Il sert uniquement à comparer des plans entre eux : un plan à coût 500 est jugé plus efficace qu'un plan à coût 5 000.

Existe-t-il des outils pour visualiser les plans d'exécution ?

Oui. explain.dalibo.com est un outil en ligne qui transforme la sortie JSON d'EXPLAIN PostgreSQL en graphe interactif coloré. pgAdmin intègre un visualiseur graphique natif. Pour MySQL, MySQL Workbench offre un affichage visuel similaire avec des indicateurs de coût par nœud.


Conclusion

Maîtriser EXPLAIN et EXPLAIN ANALYZE transforme votre rapport aux performances SQL. Plutôt que de modifier des requêtes au hasard en espérant un gain, vous diagnostiquez avec précision, vous comprenez les choix de l'optimiseur, et vous agissez là où c'est vraiment utile. C'est une compétence directement valorisée en entretien et en production.

Pour aller plus loin dans votre préparation, entraînez-vous sur des requêtes réelles avec des jeux de données significatifs. La plateforme SQL Pratique met à votre disposition des exercices corrigés avec environnement d'exécution intégré — commencez votre préparation dès aujourd'hui.

Prêt à vous entraîner ?

50 exercices SQL interactifs avec éditeur en ligne, chronomètre et feedback IA.

Voir les exercices