Plans d’exécution (EXPLAIN)
Progression
#Plans d’exécution (EXPLAIN)
Comprendre comment le moteur exécute une requête vous aide à poser les bons index et à réécrire des requêtes coûteuses. Un plan décrit l’ordre des opérations (scan, filtre, jointure, agrégat) et la stratégie choisie (index lookup, hash join, nested loops, tri).
#Lire un plan — notions clés
#Plan interactif (heuristique)
Filter
Join
Scan A
Scan B
Plan heuristique simplifié: Scan/Join → Filter → Aggregate
- Node: une opération (Scan, Index Scan, Join, Aggregate).
- Coût estimé: combine cardinalité (lignes attendues) et coût I/O/CPU.
- Ordre: l’arbre se lit de bas en haut; chaque nœud consomme ses enfants.
Exemple (pseudo‑plan):
bg-[rgba(var(--code-inline-bg),0.5)] text-[rgb(var(--fg))] px-1 roundedbg-[rgba(var(--code-inline-bg),0.5)] text-[rgb(var(--fg))] px-1 rounded
1Aggregate (sum)2 -> Hash Join (users.id = orders.user_id)3 -> Seq Scan users4 -> Index Scan orders(user_id)
Interprétation: on scanne users
, on cherche les orders
via index, on joint en hash, puis on agrège.
#Animation: pipeline d’exécution
Parser
Analyse et construction AST
Rewriter
Simplifications, pushdown des prédicats
Planner
Choix des index, type de join
Executor
Scans/joins/agrégats en flux
Résultat
Retour des lignes/agrégats
#Ajuster la requête
- Filtrer tôt: pousser les
WHERE
en amont réduit les lignes intermédiaires. - Index alignés: index sur colonnes filtrées/jointes dans le bon ordre (égalité → plage → tri).
- SARGability: éviter les fonctions côté colonne; préférer des bornes.
#Atelier rapide
Sur une base jouet: users(id, name), orders(id, user_id, amount)
.
- Sans index:
select sum(amount) from orders join users using(user_id) where users.name like 'A%'
. - Créez index
(user_id)
surorders
, index(name)
surusers
. - Réexécutez; discutez de l’impact attendu du plan.
#Bonnes pratiques
- Mesurez avant/après (temps, plan, lignes retournées).
- Gardez des index minimalistes mais efficaces (supprimez les orphelins).
- Analysez les stats (ANALYZE) quand le moteur en dépend.
#Mini‑exercice: prédire un plan
Base: orders(user_id, created_at, status, amount)
, index existants: (user_id)
, (created_at)
, aucun index composite.
Question: pour select sum(amount) from orders where user_id=42 and created_at>=date('now','-7 days')
, quel plan attendez‑vous sur un moteur classique (SQLite/Postgres) ?
Pistes:
- Sans index composite
(user_id, created_at)
, le plan peut choisir un index suruser_id
puis filtrer par date (ou l’inverse) selon la sélectivité. - Un index composite aligné sur les prédicats (égalité puis plage) améliore la sélectivité:
(user_id, created_at)
.