Skip to content

EXPLAIN – Analyser les requêtes

Bonne lecture et bon apprentissage !
Junior TSAFACK – 08/08/2026
⏱️ Temps de lecture estimé : 7 minutes


Dans le langage SQL, l’instruction EXPLAIN est à utiliser juste avant un SELECT et permet d’afficher le plan d’exécution d’une requête SQL. Cela permet de savoir de quelle manière le Système de Gestion de Base de Données (SGBD) va exécuter la requête, s’il va utiliser des index et lesquels.

Bon à savoir : En utilisant cette commande, la requête ne renverra pas les résultats du SELECT mais plutôt une analyse de cette requête. C’est un outil indispensable pour l’optimisation des performances.


La syntaxe ci-dessous représente une requête SQL utilisant la commande EXPLAIN pour MySQL ou PostgreSQL :

EXPLAIN SELECT * FROM utilisateur ORDER BY id DESC;

Rappel : Dans cet exemple, la requête retournera des informations sur le plan d’exécution, mais n’affichera pas les « vrais » résultats de la requête.


Le nom de cette instruction diffère selon les SGBD :

SGBD Commande
MySQL EXPLAIN
MariaDB EXPLAIN
PostgreSQL EXPLAIN (et EXPLAIN ANALYZE pour l’exécution réelle)
Oracle EXPLAIN PLAN
SQLite EXPLAIN QUERY PLAN
SQL Server SET SHOWPLAN_ALL ON; ou SET STATISTICS PROFILE ON;

Bon à savoir : Le résultat de cette instruction est différent selon les SGBD. Il est important de consulter la documentation de votre SGBD pour interpréter correctement les résultats.


Pour expliquer concrètement le fonctionnement de l’instruction EXPLAIN, nous allons prendre une table des fuseaux horaires.

Création de la table « timezones » (MySQL) :

CREATE TABLE IF NOT EXISTS `timezones` (
`timezone_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`timezone_groupe_fr` varchar(50) DEFAULT NULL,
`timezone_groupe_en` varchar(50) DEFAULT NULL,
`timezone_detail` varchar(100) DEFAULT NULL,
PRIMARY KEY (`timezone_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=698;

Cette table contient plusieurs centaines d’enregistrements (les fuseaux horaires du monde).


Imaginons que l’on souhaite compter le nombre de fuseaux horaires par groupe, en français. Pour cela, nous pouvons utiliser la requête SQL suivante :

SELECT timezone_groupe_fr, COUNT(timezone_detail) AS total_timezone
FROM timezones
GROUP BY timezone_groupe_fr
ORDER BY timezone_groupe_fr ASC;

Utilisation de EXPLAIN pour analyser la requête

Section titled “Utilisation de EXPLAIN pour analyser la requête”

Nous allons voir dans notre exemple comment MySQL va exécuter cette requête. Pour cela, il faut utiliser l’instruction EXPLAIN :

EXPLAIN SELECT timezone_groupe_fr, COUNT(timezone_detail) AS total_timezone
FROM timezones
GROUP BY timezone_groupe_fr
ORDER BY timezone_groupe_fr ASC;

Résultat (MySQL) :

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE timezones ALL NULL NULL NULL NULL 421 Using temporary; Using filesort
Colonne Valeur Explication
id 1 Identifiant du SELECT (un seul ici)
select_type SIMPLE Type de SELECT (simple, sans sous-requête ni union)
table timezones Table concernée
type ALL Type d’accès : parcours complet de la table (le moins performant)
possible_keys NULL Index potentiellement utilisables (aucun)
key NULL Index effectivement utilisé (aucun)
key_len NULL Longueur de la clé utilisée
ref NULL Colonnes ou constantes utilisées pour la jointure
rows 421 Estimation du nombre de lignes analysées
Extra Using temporary; Using filesort Utilisation d’une table temporaire et d’un tri externe

Interprétation :

  • type = ALL : MySQL parcourt toute la table (scan complet). C’est le moins efficace.
  • possible_keys = NULL : aucun index n’est disponible pour cette colonne.
  • Extra = Using temporary; Using filesort : MySQL doit créer une table temporaire pour le GROUP BY et faire un tri (ORDER BY). C’est coûteux en ressources.

Conclusion : Cette requête est très lourde sur une table de 421 lignes. Sur une table de plusieurs millions de lignes, elle serait rédhibitoire.


Ajout d’un index pour optimiser la requête

Section titled “Ajout d’un index pour optimiser la requête”

Il est possible d’ajouter un index sur la colonne timezone_groupe_fr pour améliorer les performances :

ALTER TABLE timezones ADD INDEX (timezone_groupe_fr);

Exécutons à nouveau la même requête avec EXPLAIN :

EXPLAIN SELECT timezone_groupe_fr, COUNT(timezone_detail) AS total_timezone
FROM timezones
GROUP BY timezone_groupe_fr
ORDER BY timezone_groupe_fr ASC;

Résultat :

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE timezones index timezone_groupe_fr timezone_groupe_fr 153 NULL 421 NULL

Interprétation des changements :

Colonne Ancienne valeur Nouvelle valeur Explication
type ALL index Utilisation de l’index
possible_keys NULL timezone_groupe_fr Index disponible
key NULL timezone_groupe_fr Index effectivement utilisé
key_len NULL 153 Longueur de la clé utilisée
Extra Using temporary; Using filesort NULL Plus besoin de table temporaire ni de tri

Conclusion : L’ajout de l’index a transformé la requête. Elle est maintenant beaucoup plus efficace, et il n’est plus nécessaire de créer une table temporaire.


PostgreSQL propose EXPLAIN ANALYZE qui exécute réellement la requête et affiche des statistiques précises (temps d’exécution, nombre de lignes réelles, etc.) :

EXPLAIN ANALYZE
SELECT timezone_groupe_fr, COUNT(timezone_detail) AS total_timezone
FROM timezones
GROUP BY timezone_groupe_fr
ORDER BY timezone_groupe_fr ASC;

Résultat (PostgreSQL) :

GroupAggregate (cost=12.34..18.56 rows=10 width=48) (actual time=0.123..0.456 rows=10 loops=1)
Group Key: timezone_groupe_fr
-> Index Only Scan using idx_timezone_groupe_fr on timezones (cost=0.28..10.42 rows=421 width=48) (actual time=0.019..0.156 rows=421 loops=1)
Planning Time: 0.089 ms
Execution Time: 0.523 ms

Interprétation :

  • cost : coût estimé (unités arbitraires).
  • actual time : temps réel d’exécution.
  • rows : nombre de lignes traitées.
  • Execution Time : temps total d’exécution de la requête.

La colonne type est cruciale pour évaluer la performance. Voici les types d’accès du plus efficace au moins efficace :

Type Description
system Table avec une seule ligne (meilleur cas possible)
const Une seule ligne correspond (clé primaire ou unique)
eq_ref Une seule ligne pour chaque ligne de la table précédente (jointure sur clé primaire)
ref Plusieurs lignes correspondent (index simple)
range Recherche dans un intervalle (BETWEEN, >, <)
index Parcours complet d’un index (meilleur qu’un scan complet de la table)
ALL Parcours complet de la table (le pire)

Objectif : obtenir const, eq_ref, ref ou range si possible. Éviter ALL.


Les valeurs les plus courantes dans la colonne Extra :

Valeur Signification
Using index L’index couvre toutes les colonnes nécessaires (pas besoin d’accéder à la table)
Using where Le SGBD filtre les lignes avec la clause WHERE après avoir lu la table
Using temporary Utilisation d’une table temporaire (souvent pour GROUP BY ou DISTINCT)
Using filesort Tri externe nécessaire (pas d’index pour ORDER BY)
Using index condition Utilisation de l’optimisation “Index Condition Pushdown” (ICP)

  1. Utilisez EXPLAIN systématiquement pour les requêtes complexes ou lentes.

  2. Cherchez les ALL et les Using temporary; Using filesort : ce sont des signaux d’alerte indiquant qu’un index pourrait améliorer les performances.

  3. Vérifiez que vos index sont bien utilisés (key doit être non NULL).

  4. Testez avec des données réelles (ou une copie représentative). Les plans d’exécution peuvent changer selon la distribution des données.

  5. Comparez avant / après pour mesurer l’impact de vos optimisations.

  6. Surveillez les index composites : ils sont utilisés uniquement si les colonnes sont dans l’ordre.

  7. Pour PostgreSQL, utilisez EXPLAIN ANALYZE pour obtenir des temps d’exécution réels (attention, la requête est exécutée).


Erreur Cause Solution
Index créé mais pas utilisé Colonne non sélective ou type incompatible Vérifier la colonne et le type
Using temporary malgré un index L’index ne couvre pas la requête Ajouter un index composite
Using filesort malgré un index L’ORDER BY ne peut pas utiliser l’index Indexer la colonne de tri
Résultat différent selon l’environnement Données différentes (taille, distribution) Tester avec des données représentatives

Vous savez désormais comment analyser vos requêtes avec EXPLAIN pour optimiser les performances. Il ne reste plus qu’à apprendre à commenter vos requêtes pour les rendre plus compréhensibles.

👉 Chapitre 46 : Commentaires SQL – Documenter vos requêtes


Bonne continuation !
Junior TSAFACK – 08/08/2026