MongoDB Academy · Leçon

Lire la sortie de explain() pour diagnostiquer les requêtes

Les apprenants interpréteront les étapes IXSCAN et COLLSCAN dans la sortie de explain et identifieront les index manquants à partir des rapports entre nReturned et docsExamined.

Leçon 4 sur 413 étapes

Lire la sortie de explain() pour diagnostiquer les requêtes est une leçon MongoDB Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage MongoDB Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours MongoDB Academy comprend 4 leçons au total.

Pourquoi explain() est important

Les requêtes lentes dans MongoDB sont généralement dues à des index manquants ou à des plans de requête sous-optimaux. La méthode explain() révèle exactement ce que MongoDB a fait pour exécuter une requête : quel index a été choisi, combien de documents ont été analysés et combien de temps chaque étape a pris. Sans explain(), l’optimisation des performances repose sur des suppositions ; avec lui, vous obtenez un rapport de diagnostic précis.

// Three verbosity levels
db.users.find({ age: { $gt: 25 } }).explain();              // 'queryPlanner'
db.users.find({ age: { $gt: 25 } }).explain('executionStats'); // includes timing
db.users.find({ age: { $gt: 25 } }).explain('allPlansExecution'); // all candidate plans

Mode queryPlanner

Le mode explain() par défaut renvoie la sortie du planificateur de requêtes : le plan gagnant et les plans rejetés, mais sans exécuter réellement la requête. Ce mode est rapide et utile pour examiner rapidement la structure du plan. Le champ principal est winningPlan, qui décrit l’arborescence des étapes d’exécution que MongoDB utiliserait.

const result = db.orders.find({ userId: 'u1' }).explain();

// winningPlan shows the chosen execution strategy
console.log(JSON.stringify(result.queryPlanner.winningPlan, null, 2));
// Example:
// { 'stage': 'FETCH',
//   'inputStage': {
//     'stage': 'IXSCAN',
//     'indexName': 'userId_1' } }

IXSCAN ou COLLSCAN

Les deux noms d’étape les plus importants dans la sortie de explain() sont : IXSCAN (analyse d’index) — la requête a utilisé un index ; et COLLSCAN (analyse de collection) — MongoDB a analysé chaque document. Un COLLSCAN sur une collection de production contenant des millions de documents est presque toujours un problème. La présence de COLLSCAN est le premier signe indiquant que vous devez ajouter ou améliorer un index.

// BAD: COLLSCAN means no usable index
// { 'stage': 'COLLSCAN', 'filter': { 'email': { '$eq': 'a@b.com' } } }

// GOOD: IXSCAN means an index was used
// { 'stage': 'IXSCAN', 'indexName': 'email_1', 'direction': 'forward' }

// Fix: create the missing index
db.users.createIndex({ email: 1 });

Mode executionStats

explain('executionStats') exécute réellement la requête et recueille des données de durée. Les métriques les plus importantes sont : nReturned — les documents renvoyés au client ; totalDocsExamined — les documents examinés par MongoDB ; et totalKeysExamined — les entrées d’index analysées. Une requête efficace devrait avoir nReturned ≈ totalDocsExamined. Un écart important révèle un travail inutile.

const stats = db.orders
  .find({ userId: 'u1', status: 'active' })
  .explain('executionStats');

const s = stats.executionStats;
console.log('Returned:       ', s.nReturned);
console.log('Keys Examined:  ', s.totalKeysExamined);
console.log('Docs Examined:  ', s.totalDocsExamined);
console.log('Execution ms:   ', s.executionTimeMillis);

Interpréter les ratios clés

Trois ratios vous indiquent l’efficacité d’une requête : clés examinées / clés renvoyées (un ratio faible est bon, 1:1 est idéal), documents examinés / documents renvoyés (devrait être proche de 1) et documents examinés / clés examinées (une valeur bien supérieure à 1 signifie que l’index filtre efficacement, mais que la récupération est coûteuse). Ces ratios vous aident à déterminer si vous avez besoin d’un meilleur index, d’une requête couverte ou d’une autre stratégie de filtrage.

// Efficiency check formula
const ratio = s.totalDocsExamined / s.nReturned;
// ratio = 1  -> perfect, index is very selective
// ratio = 10 -> for every doc returned, 10 were scanned (room to improve)
// ratio = 1000+ -> strong signal to add or redesign index

L’étape FETCH

Après qu’un IXSCAN a identifié les entrées d’index correspondantes, MongoDB peut devoir effectuer un FETCH des documents réels depuis le disque pour vérifier les conditions qui ne sont pas couvertes par l’index ou pour renvoyer des champs absents de l’index. Une requête couverte élimine entièrement l’étape FETCH. Si vous voyez IXSCAN → FETCH avec une valeur élevée de totalDocsExamined, envisagez d’ajouter les champs projetés à l’index afin de permettre la couverture.

// With IXSCAN only on userId, fetching to check 'status' adds FETCH
// winningPlan:
// { stage: 'FETCH',
//   filter: { status: { $eq: 'active' } },
//   inputStage: { stage: 'IXSCAN', indexName: 'userId_1' } }

// Fix: compound index so status is in the index too
db.orders.createIndex({ userId: 1, status: 1 });
// Now: IXSCAN only, no FETCH needed for the filter

Plans rejetés et cache des plans

MongoDB évalue en parallèle plusieurs plans candidats pendant une exécution d’essai et sélectionne le gagnant en fonction du nombre de documents que chaque plan renvoie par unité de travail. Le plan gagnant est mis en cache pour cette forme de requête, afin que les exécutions suivantes évitent une nouvelle évaluation. Vous pouvez afficher les plans rejetés avec le niveau de verbosité allPlansExecution. Le cache est invalidé lorsque les index changent ou que les statistiques de la collection sont mises à jour de manière importante.

// See all candidate plans and why the winner was chosen
const allPlans = db.orders
  .find({ userId: 'u1', status: 'active' })
  .explain('allPlansExecution');

// rejectedPlans shows what MongoDB tried but discarded
console.log(allPlans.queryPlanner.rejectedPlans.length, 'plans rejected');

Étapes SORT et SORT_KEY

Lorsque MongoDB ne peut pas utiliser un index pour satisfaire un tri, il ajoute au plan une étape SORT en mémoire. Les tris en mémoire sont limités à 100 MB par défaut ; au-delà, la requête échoue, sauf si vous activez allowDiskUse. La présence d’une étape SORT indique qu’il faut ajouter un index composé dont l’ordre des clés correspond à celui du tri, afin d’éliminer entièrement le tri en mémoire.

// explain shows in-memory sort when index doesn't cover the sort order
// { stage: 'SORT', sortPattern: { createdAt: -1 },
//   inputStage: { stage: 'IXSCAN', ... } }

// Fix: compound index that includes the sort field
db.orders.createIndex({ userId: 1, createdAt: -1 });
// Now the SORT stage disappears from the plan

Forcer un index avec hint()

Le planificateur de requêtes de MongoDB choisit généralement le meilleur index, mais il sélectionne parfois un plan sous-optimal, notamment lorsque les statistiques sont obsolètes. Vous pouvez forcer l’utilisation d’un index précis avec .hint(), en transmettant soit le modèle de clés de l’index, soit son nom. C’est utile pour le débogage, afin de comparer les plans, ou en dernier recours en production lorsque le planificateur fait de mauvais choix.

// Force use of a specific index by key pattern
db.orders.find({ userId: 'u1', status: 'active' })
  .hint({ userId: 1, status: 1 })
  .explain('executionStats');

// Force by index name
db.orders.find({ userId: 'u1' })
  .hint('idx_orders_user');

// Force a COLLSCAN (bypass all indexes)
db.orders.find({ userId: 'u1' })
  .hint({ $natural: 1 });

explain() sur les pipelines d’agrégation

Les pipelines d’agrégation prennent également en charge explain(). Transmettez { explain: true } à aggregate() pour voir comment les étapes du pipeline s’exécutent et si les premières étapes, comme $match, utilisent des index. L’idée essentielle est la suivante : un $match au début du pipeline peut transmettre un filtre à un IXSCAN ; un $match placé après un $group ne le peut pas.

// explain() on an aggregation pipeline
db.orders.explain('executionStats').aggregate([
  { $match: { userId: 'u1', status: 'active' } }, // <-- pushed to IXSCAN
  { $group: { _id: '$productId', total: { $sum: '$amount' } } },
  { $sort: { total: -1 } }
]);

Signaux d’alerte courants dans explain()

Lorsque vous examinez la sortie de explain(), surveillez les signes d’alerte suivants : un COLLSCAN sur une grande collection ; une valeur de totalDocsExamined nettement supérieure à nReturned ; une étape SORT en mémoire ; ou une valeur de executionTimeMillis supérieure à votre SLA. Chacun de ces signes indique une correction précise : ajouter un index, modifier l’ordre des clés de l’index, ajouter les champs de tri à l’index composé ou repenser la requête.

// Red flag checklist:
// 1. stage: 'COLLSCAN' -> add index
// 2. totalDocsExamined >> nReturned -> compound index or partial index
// 3. stage: 'SORT' -> extend compound index to cover sort order
// 4. executionTimeMillis > 100 -> investigate stages above

Vérification rapide

Testez votre compréhension de la sortie de explain() de MongoDB abordée dans cette leçon.

Récapitulatif de la leçon

Dans cette leçon, vous avez appris que explain('executionStats') exécute la requête et fournit sa durée ainsi que le nombre de documents, que COLLSCAN ou IXSCAN dans le plan gagnant indique immédiatement si un index a été utilisé et que le ratio nReturned / totalDocsExamined mesure l’efficacité de l’index. Nous allons maintenant découvrir les index textuels pour la recherche en texte intégral.

Gratuit pour commencer

Apprends JavaScript avec un tuteur IA — gratuit

Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.

Cours
30
Leçons
120

Questions Fréquemment Posées

La leçon « Lire la sortie de explain() pour diagnostiquer les requêtes » est-elle gratuite ?

Oui — le texte complet de « Lire la sortie de explain() pour diagnostiquer les requêtes » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours MongoDB Academy, passe à CoddyKit PRO. Le cours MongoDB Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Lire la sortie de explain() pour diagnostiquer les requêtes » ?

Les apprenants interpréteront les étapes IXSCAN et COLLSCAN dans la sortie de explain et identifieront les index manquants à partir des rapports entre nReturned et docsExamined. Tu pratiques MongoDB Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer MongoDB Academy ?

Aucune expérience préalable n'est requise. MongoDB Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.

Combien de temps prend la leçon « Lire la sortie de explain() pour diagnostiquer les requêtes » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon MongoDB Academy ?

Oui. Chaque leçon MongoDB Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Fonctionnement des index B-tree de MongoDB
  2. Créer des index à un champ et composés
  3. Propriétés des index : unique, sparse, partial, TTL
  4. Lire la sortie de explain() pour diagnostiquer les requêtes
← Retour à MongoDB Academy