Réponse A: Anthropic Claude Fable 5
Comprendre les index de base de données : un guide pratique
Ce qu’est un index
Un index de base de données est une structure de données séparée que la base maintient en parallèle d’une table. Il stocke les valeurs d’une ou plusieurs colonnes sous une forme triée et interrogeable, avec des pointeurs vers les lignes réelles. La table elle‑même stocke vos données ; l’index est une structure supplémentaire dont le seul rôle est d’aider la base à trouver les lignes plus rapidement.
Voici une analogie, et c’est la seule dont vous avez besoin : un index ressemble à l’index à la fin d’un manuel. Si vous voulez toutes...
Afficher la réponse complète ▼
Comprendre les index de base de données : un guide pratique
Ce qu’est un index
Un index de base de données est une structure de données séparée que la base maintient en parallèle d’une table. Il stocke les valeurs d’une ou plusieurs colonnes sous une forme triée et interrogeable, avec des pointeurs vers les lignes réelles. La table elle‑même stocke vos données ; l’index est une structure supplémentaire dont le seul rôle est d’aider la base à trouver les lignes plus rapidement.
Voici une analogie, et c’est la seule dont vous avez besoin : un index ressemble à l’index à la fin d’un manuel. Si vous voulez toutes les pages qui mentionnent « transactions », vous ne lisez pas tout le livre page par page ; vous recherchez « transactions » dans l’index trié par ordre alphabétique, obtenez une courte liste de numéros de page et allez directement à celles‑ci. Sans cet index, votre seule option est de parcourir chaque page. Une base de données est face exactement au même choix : utiliser un index pour sauter aux lignes correspondantes, ou scanner la table entière.
Maintenant le comportement réel, sans l’analogie. Lorsque vous exécutez une requête comme SELECT * FROM orders WHERE customer_id = 42, la base a deux stratégies de base. Un parcours complet de la table lit chaque ligne et vérifie la condition, ce qui coûte un temps proportionnel à la taille de la table. Une recherche via l’index parcourt plutôt la structure d’index triée pour customer_id = 42, trouve rapidement les entrées correspondantes et suit les pointeurs enregistrés pour récupérer seulement ces lignes. Pour une table volumineuse où seules quelques lignes correspondent, la voie de l’index peut être des milliers de fois moins coûteuse.
Comment fonctionne un index B‑tree, de façon générale
Le type d’index le plus courant est un B‑tree. C’est une structure d’arbre équilibré où les clés sont conservées en ordre trié. Le nœud supérieur divise l’espace des clés en plages, chaque nœud enfant subdivise davantage, et le niveau inférieur (les feuilles) contient les valeurs indexées réelles avec des pointeurs vers les lignes de la table. Parce que l’arbre est équilibré et que chaque nœud contient de nombreuses clés, même une table de centaines de millions de lignes nécessite généralement seulement trois à cinq lectures de nœuds pour trouver une valeur spécifique.
Parce qu’un B‑tree conserve les valeurs en ordre trié, il prend en charge plus que des correspondances exactes. Il gère efficacement les conditions de plage (WHERE created_at >= '2024-01-01'), les correspondances de préfixe sur les chaînes (WHERE email LIKE 'anna%'), et peut renvoyer des lignes déjà triées, ce qui permet à la base d’éviter une étape de tri séparée pour les clauses ORDER BY correspondantes.
Pourquoi les index ont un coût
Les index ne sont pas gratuits, et c’est le compromis que vous devez intégrer.
Les écritures ralentissent. Chaque INSERT doit ajouter une entrée à chaque index sur la table. Chaque DELETE doit supprimer des entrées. Chaque UPDATE qui modifie une colonne indexée doit mettre à jour les entrées d’index correspondantes. Une table avec six index effectue effectivement jusqu’à sept écritures pour chaque insertion logique de ligne. Sur des tables à fort volume d’écritures, un indexage négligent nuit de manière mesurable au débit.
Le stockage augmente. Chaque index est une copie complète des valeurs de colonne indexées plus des pointeurs et la structure de l’arbre. Les index sur de grandes tables peuvent rivaliser avec la taille de la table elle‑même ou la dépasser, ce qui affecte aussi les sauvegardes et la mise en cache en mémoire.
Donc le principe directeur est : les index échangent un coût d’écriture et d’espace de stockage contre la vitesse de lecture. Vous les ajoutez là où les lectures en bénéficient clairement, pas partout.
Sélectivité : le concept clé pour décider de la valeur
La sélectivité décrit dans quelle mesure une condition réduit le nombre de lignes. Une colonne hautement sélective a beaucoup de valeurs distinctes par rapport au nombre de lignes. Un email ou un identifiant de commande est très sélectif : filtrer dessus renvoie une ou quelques lignes sur des millions, et un index est très utile. Une colonne comme status avec trois valeurs ('pending', 'shipped', 'cancelled') ou un drapeau booléen is_active a une faible sélectivité : le filtrage peut toujours correspondre à 40 % de la table.
Pourquoi cela importe‑t‑il ? Si une condition correspond à une grande fraction de la table, aller et venir entre l’index et la table pour des millions de lignes est souvent plus lent que de simplement scanner la table séquentiellement. Les planificateurs de requêtes le savent et ignoreront un index lorsque la fraction estimée de correspondance est trop élevée. À titre d’intuition approximative, si une requête typique utilisant l’index renverrait plus que quelques pourcents des lignes, l’index peut ne pas être utilisé du tout, et il constitue alors un surcoût pur.
Index composites et règle du préfixe le plus à gauche
Un index peut couvrir plusieurs colonnes, dans un ordre spécifique. Par exemple :
CREATE INDEX idx_orders_customer_date ON orders (customer_id, created_at);
Considérez cela comme triant les entrées d’abord par customer_id, puis par created_at au sein de chaque client, comme un annuaire téléphonique trié par nom de famille, puis par prénom.
L’idée du préfixe le plus à gauche découle directement de cet ordre de tri. Cet index peut servir efficacement :
- WHERE customer_id = 42
- WHERE customer_id = 42 AND created_at >= '2024-01-01'
Mais il ne peut pas servir efficacement WHERE created_at >= '2024-01-01' seul, parce que les entrées pour une plage de dates donnée sont réparties entre tous les clients ; vous ne pouvez pas utiliser un annuaire trié par nom de famille pour trouver toutes les personnes prénommées « Anna ». L’index est utilisable seulement lorsque vos conditions contraignent un préfixe de sa liste de colonnes, en commençant par la colonne la plus à gauche. Cela signifie que (customer_id, created_at) et (created_at, customer_id) sont des index différents servant des requêtes différentes, et l’ordre des colonnes doit suivre vos modèles de requêtes les plus importants. Une règle empirique commune : mettez d’abord les colonnes filtrées par égalité, puis la colonne de plage ou de tri.
Quand un index n’aide pas
- Faible sélectivité : filtrer WHERE is_active = true sur une table où 90 % des lignes sont actives. Le planificateur fera un scan à la place.
- Fonctions ou expressions sur la colonne : WHERE LOWER(email) = 'x@y.com' ne peut pas utiliser un index simple sur email, parce que l’index stocke les valeurs brutes, pas les valeurs transformées. (Certaines bases de données prennent en charge des index d’expression, mais l’index simple ne sera pas utilisé.)
- Wildcards en tête : WHERE name LIKE '%son' ne peut pas utiliser un B‑tree, car l’ordre trié n’aide que lorsque le préfixe est connu.
- Sauter la colonne la plus à gauche d’un index composite, comme décrit ci‑dessus.
- Tables minuscules : pour quelques centaines de lignes, un scan est déjà rapide ; l’index ajoute un coût d’écriture sans bénéfice.
- Incompatibilités de type ou conversions implicites sur la colonne indexée peuvent aussi empêcher l’utilisation de l’index.
Deux petits exemples
Un index utile. Supposons que votre application exécute constamment :
SELECT id, total, created_at
FROM orders
WHERE customer_id = 42
ORDER BY created_at DESC
LIMIT 20;
Alors cet index convient parfaitement :
CREATE INDEX idx_orders_customer_date ON orders (customer_id, created_at);
La base saute aux entrées du client 42, qui sont déjà triées par created_at, lit les 20 plus récentes, et s’arrête. C’est rapide sur une table de n’importe quelle taille, et il sert aussi les recherches simples par customer_id grâce au préfixe le plus à gauche.
Un index problématique. Supposons que vous créiez plutôt :
CREATE INDEX idx_orders_status ON orders (status);
où status a trois valeurs possibles et la plupart des lignes sont 'shipped'. Une requête comme SELECT * FROM orders WHERE status = 'shipped' correspond à la majeure partie de la table, donc le planificateur fera de toute façon un scan de la table. L’index est rarement ou jamais utilisé, pourtant chaque insert et chaque mise à jour du status paie pour le maintenir. C’est une perte nette. (Une exception à connaître : indexer une colonne de faible cardinalité peut être rentable quand une valeur est rare et fortement interrogée, comme le petit ensemble de commandes 'pending', mais la version générique ci‑dessus est une erreur classique.)
Checklist pratique avant d’ajouter un index
- Identifiez d’abord la requête réellement lente ; n’indexez pas de manière spéculative. Regardez les vrais modèles de requêtes et utilisez EXPLAIN pour voir le plan actuel.
- Vérifiez la sélectivité : les requêtes typiques utilisant cet index renverront‑elles une petite fraction de la table ? Sinon, reconsidérez.
- Pour les filtres et tris sur plusieurs colonnes, concevez un index composite unique avec le bon ordre de colonnes (colonnes d’égalité en premier, puis colonnes de plage/tri) plutôt que plusieurs index mono‑colonne.
- Confirmez la règle du préfixe le plus à gauche : votre requête la plus courante contraint‑elle la première colonne de l’index ?
- Assurez‑vous que la requête ne neutralise pas l’index avec des fonctions, des wildcards en tête, ou des conversions de type sur la colonne indexée.
- Pesez le trafic d’écriture : sur des tables fortement écrites, chaque index supplémentaire a un coût réel. Supprimez les index qui se chevauchent ou qui sont des préfixes d’autres.
- Vérifiez si un index existant couvre déjà la requête avant d’en créer un nouveau.
- Après avoir créé l’index, vérifiez avec EXPLAIN que le planificateur l’utilise réellement, et mesurez le temps de la requête avant et après.
- Passez en revue périodiquement et supprimez les index inutilisés ; ils coûtent en écritures et en stockage pour toujours.
Le modèle mental essentiel à conserver : un index est une structure de recherche triée que vous payez à chaque écriture pour que des lectures spécifiques et sélectives deviennent bon marché. Ajoutez‑en un lorsque vous pouvez nommer la requête qu’il sert et démontrer qu’il aide.
Résultat
Votes gagnants
3 / 3
Score moyen
Score total
Commentaire global
La réponse A est complète, précise et exceptionnellement bien adaptée au public cible. Elle sépare clairement l'analogie du comportement réel de la base de données (comme demandé explicitement par l'énoncé), explique la structure B-tree avec des détails concrets sur les lectures de nœuds, et couvre les coûts d'écriture, le stockage et la sélectivité avec une nuance correcte, y compris le cas où l'indexation d'une valeur rare à faible cardinalité peut quand même être bénéfique. Elle aborde pleinement les index composites et la règle du préfixe le plus à gauche avec une excellente illustration de l'annuaire téléphonique, et inclut une section riche sur « quand un index n'aide pas » (fonctions, jokers en tête, transtypages, petites tables). Les deux exemples SQL sont cohérents et directement liés aux modèles de requêtes, et la liste de contrôle est très exploitable, faisant référence à EXPLAIN, à la mesure et à la suppression des index inutilisés. Faiblesse mineure : elle est plus longue et plus dense que strictement nécessaire, mais cela nuit rarement à la compréhension étant donné la structure solide.
Afficher le détail de l’évaluation ▼
Clarté
Poids 30%Les explications sont précises et s'enchaînent logiquement ; la séparation délibérée de l'analogie du comportement réel, l'illustration de l'annuaire téléphonique pour l'ordre des colonnes et le modèle mental final rendent les concepts abstraits vivants. Légèrement plus dense que B mais jamais confuse.
Exactitude
Poids 25%Techniquement précise tout au long, y compris sur des points subtils : les planificateurs ignorant les index de faible sélectivité, les index d'expression comme exception, l'échec des jokers en tête, les problèmes de transtypage, et la note correcte qu'une valeur rare à faible cardinalité fréquemment interrogée peut quand même être bénéfique. L'estimation de la lecture des nœuds B-tree est raisonnable.
Adéquation au public
Poids 20%Bien adaptée à un développeur junior connaissant SELECT/WHERE/JOIN : elle évite les détails internes profonds, nomme les règles pratiques et lie chaque concept à une décision que le développeur peut prendre. La densité est le seul risque mineur pour un novice.
Complétude
Poids 15%Couvre tous les éléments demandés et plus encore : structure de l'index, accélération des lectures, coût d'écriture/stockage, B-tree de haut niveau, sélectivité, index composites, préfixe le plus à gauche, plusieurs cas où l'index n'aide pas, deux exemples SQL contrastés, et une liste de contrôle riche incluant EXPLAIN et la suppression des index inutilisés.
Structure
Poids 10%Flux logique et bien sectionné, de la définition aux compromis, en passant par la sélectivité, les index composites, les cas où l'index n'aide pas, les exemples et la liste de contrôle. Des blocs de texte légèrement plus denses réduisent la lisibilité par rapport à B.
Score total
Commentaire global
La réponse A fournit une explication exceptionnellement claire, complète et pratique des index de base de données, parfaitement adaptée à un développeur backend junior. Elle couvre tous les sujets requis avec une excellente profondeur, y compris une section robuste sur les situations où les index n'aident pas et une liste de contrôle très exploitable. Les analogies et les explications directes sont bien intégrées, et les exemples SQL sont pertinents.
Afficher le détail de l’évaluation ▼
Clarté
Poids 30%La réponse A est exceptionnellement claire, utilisant des titres bien structurés, un langage précis et des analogies efficaces (comme l'annuaire pour le préfixe gauche) pour expliquer des concepts complexes. Le flux est logique et facile à suivre.
Exactitude
Poids 25%La réponse A est très précise dans toutes ses explications, de la mécanique des B-trees aux nuances de sélectivité et des index composites. Elle identifie correctement divers scénarios où les index sont bénéfiques ou préjudiciables, y compris le support des requêtes de plage et des clauses ORDER BY avec des B-trees.
Adéquation au public
Poids 20%La réponse A est parfaitement adaptée à un développeur backend junior. Le langage est accessible, l'analogie est simple et efficace, et les conseils pratiques sont complets sans être écrasants. Le 'modèle mental de base' à la fin est un excellent résumé pour le public cible.
Complétude
Poids 15%La réponse A est très complète, couvrant tous les sujets demandés en profondeur. Elle fournit une liste très complète des situations où un index peut ne pas aider et une liste de contrôle détaillée et exploitable, dépassant les attentes en matière de conseils pratiques.
Structure
Poids 10%La réponse A a une excellente structure avec des titres clairs et descriptifs qui guident le lecteur à travers le matériel de manière logique. Chaque concept est introduit et expliqué de manière bien organisée, rendant le contenu facile à assimiler.
Score total
Commentaire global
La réponse A est une explication pédagogique très complète, précise et bien structurée. Elle explique clairement les index comme des structures de recherche triées séparées, couvre le comportement des arbres B, les compromis lecture/écriture/stockage, la sélectivité, les index composites, le comportement du préfixe le plus à gauche, et de nombreuses situations où les index peuvent ne pas aider. Ses exemples sont pratiques et sa liste de contrôle finale est directement exploitable. Les faiblesses mineures sont quelques simplifications générales, comme l'implication générique du comportement des LIKE-préfixes des arbres B et l'affirmation que l'index d'exemple est rapide sur une table de toute taille, mais cela n'altère pas matériellement l'explication.
Afficher le détail de l’évaluation ▼
Clarté
Poids 30%La réponse A est très claire, avec des explications directes, des exemples concrets et des transitions fluides de l'analogie au comportement réel de la base de données. Elle est quelque peu longue, mais le détail améliore généralement la compréhension plutôt que de l'obscurcir.
Exactitude
Poids 25%La réponse A est techniquement exacte pour une base de données relationnelle générique au niveau visé. Elle explique correctement les structures d'index séparées, la recherche par arbre B, les compromis lecture/écriture/stockage, la sélectivité, l'ordre des index composites et les cas d'utilisation courants où ils ne sont pas utiles, avec seulement de légères simplifications générales.
Adéquation au public
Poids 20%La réponse A est bien adaptée à un développeur backend junior qui connaît les bases du SQL. Elle fournit des modèles mentaux pratiques, des exemples réalistes et des conseils exploitables, bien que sa largeur puisse être un peu dense pour une première introduction.
Complétude
Poids 15%La réponse A couvre presque tous les éléments demandés : ce que sont les index, l'accélération des lectures, les coûts d'écriture et de stockage, le comportement des arbres B, la sélectivité, les index composites, le comportement du préfixe le plus à gauche, plusieurs cas où les index peuvent ne pas aider, deux exemples SQL et une liste de contrôle solide.
Structure
Poids 10%La réponse A est très bien organisée, avec des titres clairs, une progression logique, des exemples placés après les concepts et une liste de contrôle pratique à la fin. La structure soutient fortement l'apprentissage.