Performance : lire EXPLAIN et choisir ses index
EXPLAIN ANALYZE : mesurer, ne pas deviner
Face Ă une requĂȘte lente, l'intuition ment (cours ML : « mesure, ne devine pas »). Le seul juge : le plan d'exĂ©cution rĂ©el.
EXPLAIN (ANALYZE, BUFFERS) SELECT ⊠;
Les nĆuds Ă reconnaĂźtre, du pire au meilleur selon le contexte :
- Seq Scan : lecture de toute la table. Catastrophe sur 10 M de lignes filtrées, mais optimal si on lit 90 % de la table (l'index coûterait plus cher) ;
- Index Scan / Index Only Scan : l'index guide (l'Only ne touche mĂȘme pas la table â index couvrant) ;
- Bitmap Heap Scan : entre les deux, pour une sélectivité moyenne ;
- Nested Loop / Hash Join / Merge Join : les trois stratĂ©gies de jointure â le planner choisit selon les volumes.
Les deux chiffres qui comptent : l'Ă©cart estimĂ© vs rĂ©el (rows=100 estimĂ©, actual rows=90000 â statistiques pĂ©rimĂ©es, ANALYZE la table) et le temps par nĆud (oĂč part le budget). Un Seq Scan en haut d'une requĂȘte Ă 3 s sur une grosse table = ton coupable habituel.
Les familles d'index (chacune son usage)
| Index | Pour | Exemple du projet |
|---|---|---|
| B-tree (dĂ©faut) | Ă©galitĂ©, ordre, plages | WHERE id = âŠ, ORDER BY created_at |
| GIN | contenu « many values » | JSONB (extensions), full-text (tsvector), trigram |
| HNSW (pgvector) | plus proches voisins vectoriels | search_vec <=> :emb (recherche sémantique) |
| partiel | sous-ensemble filtrĂ© | WHERE statut = 'pending' â index petit et ciblĂ© |
| composite | filtres multi-colonnes | (tenant_id, created_at) â l'ordre des colonnes compte ! |
RÚgle du composite : la colonne la plus sélective et filtrée par égalité en premier, celle qui ordonne ensuite ((tenant_id, created_at) sert WHERE tenant_id=⊠ORDER BY created_at).
Le coût caché des index
Un index accĂ©lĂšre les lectures mais ralentit chaque Ă©criture (il faut le maintenir) et occupe de l'espace. D'oĂč la discipline : indexer les colonnes rĂ©ellement filtrĂ©es/triĂ©es en prod (l'EXPLAIN le dit), pas « au cas oĂč ». Et surveiller les index inutilisĂ©s (pg_stat_user_indexes) â un index jamais scannĂ© est un coĂ»t d'Ă©criture pur.
Un Seq Scan est-il toujours un problĂšme ?