Introduction
Dans ce laboratoire, vous apprendrez les bases de l'utilisation des index MongoDB pour optimiser les performances des requêtes. Un index est une structure de données spéciale qui contient une petite partie des données d'une collection, facile à rechercher, permettant à MongoDB de trouver des documents beaucoup plus rapidement qu'en parcourant l'intégralité de la collection.
Vous commencerez par observer les performances d'une requête sans index. Ensuite, vous créerez des index à champ unique et des index composés et verrez comment ils améliorent considérablement les vitesses de requête et de tri. Enfin, vous apprendrez à gérer vos index en les listant et en les supprimant. À la fin de ce laboratoire, vous aurez une compréhension pratique de la création et de l'utilisation des index pour rendre vos applications MongoDB plus efficaces.
Requêtes sans index
Avant de créer un index, il est important de comprendre comment MongoDB fonctionne sans lui. Dans cette étape, vous configurerez une collection d'exemple, exécuterez une requête et analyserez son plan d'exécution pour observer l'impact sur les performances d'un parcours complet de la collection.
Tout d'abord, ouvrez le shell MongoDB (mongosh) pour interagir avec votre base de données. Cette interface en ligne de commande vous permet d'exécuter des commandes directement sur votre instance MongoDB.
mongosh
Une fois dans le shell, vous verrez l'invite >. Passons à une nouvelle base de données nommée indexlab et insérons quelques documents d'exemple dans une collection users. Si la base de données ou la collection n'existent pas, MongoDB les créera automatiquement.
use indexlab
db.users.insertMany([
{ name: "Alice", age: 28, city: "New York" },
{ name: "Bob", age: 35, city: "San Francisco" },
{ name: "Charlie", age: 42, city: "Chicago" },
{ name: "David", age: 25, city: "New York" },
{ name: "Eve", age: 31, city: "San Francisco" }
]);
Maintenant, trouvons tous les utilisateurs de plus de 30 ans. Nous utiliserons la méthode .explain("executionStats") pour voir comment MongoDB exécute cette requête. Cette méthode fournit des statistiques détaillées sur le plan d'exécution de la requête.
db.users.find({ age: { $gt: 30 } }).explain("executionStats");
La sortie fournit des statistiques détaillées sur l'exécution de la requête. Recherchez les sections winningPlan et executionStats.
Exemple de sortie (tronquée) :
{
"queryPlanner": {
"winningPlan": {
"stage": "COLLSCAN",
"filter": { "age": { "$gt": 30 } },
"direction": "forward"
}
},
"executionStats": {
"executionSuccess": true,
"nReturned": 3,
"executionTimeMillis": 0,
"totalKeysExamined": 0,
"totalDocsExamined": 5
}
}
Les informations clés ici sont stage: "COLLSCAN" et totalDocsExamined: 5.
COLLSCANsignifie "Collection Scan" (parcours de collection). Cela signifie que MongoDB a dû inspecter chaque document de la collection pour trouver ceux qui correspondent à la requête.totalDocsExamined: 5confirme que les 5 documents de la collection ont été parcourus.
Bien que cela soit rapide pour une petite collection, un parcours de collection sur des millions de documents serait très lent. Dans l'étape suivante, vous corrigerez cela en ajoutant un index.
Créer et utiliser un index sur un seul champ
Maintenant que vous avez constaté l'inefficacité d'un parcours de collection, améliorons les performances en créant un index. Un index sur le champ age permettra à MongoDB de trouver rapidement les documents pertinents sans parcourir l'intégralité de la collection.
Vous devriez toujours être dans le shell mongosh de l'étape précédente.
Créez un index sur le champ age par ordre croissant. Le 1 spécifie un index ascendant, tandis que -1 spécifierait un index descendant.
db.users.createIndex({ age: 1 });
MongoDB confirmera que l'index a été créé avec succès. Le nom par défaut de cet index sera age_1.
Exécutez maintenant la même requête que lors de l'étape précédente et examinez son plan d'exécution.
db.users.find({ age: { $gt: 30 } }).explain("executionStats");
Exemple de sortie (tronquée) :
{
"queryPlanner": {
"winningPlan": {
"stage": "FETCH",
"inputStage": {
"stage": "IXSCAN",
"keyPattern": { "age": 1 },
"indexName": "age_1"
}
}
},
"executionStats": {
"executionSuccess": true,
"nReturned": 3,
"executionTimeMillis": 0,
"totalKeysExamined": 3,
"totalDocsExamined": 3
}
}
Remarquez les changements significatifs dans le plan d'exécution :
- Le
stageest maintenantIXSCAN, qui signifie "Index Scan" (parcours d'index). Cela indique que MongoDB a utilisé l'indexage_1pour trouver les documents correspondants. totalKeysExaminedettotalDocsExaminedsont maintenant de 3, et non de 5. MongoDB n'a eu à examiner que les 3 documents qui correspondaient à la requête via l'index, ignorant les 2 autres. C'est la source du gain de performance.
Utiliser un index composé pour le tri
Les index ne servent pas seulement à accélérer les requêtes ; ils sont également essentiels pour un tri efficace. Lorsque vous triez sur un champ qui n'est pas indexé, MongoDB doit effectuer le tri en mémoire, ce qui peut être lent et consommer beaucoup de RAM. Un index composé, qui inclut plusieurs champs, peut optimiser les requêtes qui filtrent et trient sur ces champs.
Créons un index composé sur les champs city (ascendant) et age (descendant). L'ordre des champs dans l'index est important pour la manière dont il peut être utilisé.
db.users.createIndex({ city: 1, age: -1 });
Maintenant, exécutons une requête qui trie les utilisateurs par ville, puis par âge. Nous utiliserons à nouveau .explain() pour confirmer que l'index est utilisé pour le tri.
db.users.find().sort({ city: 1, age: -1 }).explain("executionStats");
Exemple de sortie (tronquée) :
{
"queryPlanner": {
"winningPlan": {
"stage": "FETCH",
"inputStage": {
"stage": "IXSCAN",
"keyPattern": { "city": 1, "age": -1 },
"indexName": "city_1_age_-1"
}
}
}
}
L'étape IXSCAN montre que MongoDB a utilisé notre nouvel index city_1_age_-1. Comme les données sont déjà ordonnées dans l'index selon nos critères de tri, MongoDB n'a pas besoin d'effectuer une étape de tri séparée et coûteuse en mémoire.
Pour voir le résultat trié réel, exécutez la requête sans .explain().
db.users.find().sort({ city: 1, age: -1 });
Sortie :
[
{ _id: ObjectId("..."), name: 'Charlie', age: 42, city: 'Chicago' },
{ _id: ObjectId("..."), name: 'Alice', age: 28, city: 'New York' },
{ _id: ObjectId("..."), name: 'David', age: 25, city: 'New York' },
{ _id: ObjectId("..."), name: 'Bob', age: 35, city: 'San Francisco' },
{ _id: ObjectId("..."), name: 'Eve', age: 31, city: 'San Francisco' }
]
Les documents sont correctement triés d'abord par city alphabétiquement, puis par age du plus âgé au plus jeune au sein de chaque ville, conformément à la définition de l'index composé.
Gérer et supprimer des index
Bien que les index améliorent les performances de lecture, ils ne sont pas gratuits. Ils consomment de l'espace de stockage et ajoutent une légère surcharge aux opérations d'écriture (insertions, mises à jour et suppressions). Par conséquent, il est de bonne pratique de revoir périodiquement et de supprimer les index qui ne sont plus utilisés.
Tout d'abord, vous pouvez lister tous les index d'une collection à l'aide de la méthode getIndexes().
db.users.getIndexes();
Sortie :
[
{ "v": 2, "key": { "_id": 1 }, "name": "_id_" },
{ "v": 2, "key": { "age": 1 }, "name": "age_1" },
{ "v": 2, "key": { "city": 1, "age": -1 }, "name": "city_1_age_-1" }
]
Ceci montre l'index par défaut sur le champ _id, qui est créé automatiquement pour chaque collection, et les deux index que nous avons créés.
Supposons que nous ayons déterminé que l'index composé city_1_age_-1 n'est plus nécessaire. Vous pouvez le supprimer à l'aide de la méthode dropIndex(), en passant le nom de l'index comme argument.
db.users.dropIndex("city_1_age_-1");
MongoDB retournera un objet indiquant combien d'index existaient avant l'opération de suppression.
{ "nIndexesWas": 3, "ok": 1 }
Maintenant, vérifiez que l'index a été supprimé en listant à nouveau les index.
db.users.getIndexes();
Sortie :
[
{ "v": 2, "key": { "_id": 1 }, "name": "_id_" },
{ "v": 2, "key": { "age": 1 }, "name": "age_1" }
]
Comme vous pouvez le constater, l'index city_1_age_-1 a disparu. Une gestion appropriée des index est un élément clé pour maintenir une base de données saine et performante.
Pour quitter le shell MongoDB, vous pouvez taper exit ou appuyer sur Ctrl+D.
exit;
Résumé
Dans ce laboratoire, vous avez appris les techniques essentielles pour utiliser les index MongoDB. Vous avez commencé par observer un COLLSCAN sur une requête sans index et compris ses limitations de performance. Vous avez ensuite créé un index à champ unique, ce qui a modifié le plan de requête pour un IXSCAN beaucoup plus efficace.
De plus, vous avez exploré les index composés et vu comment ils peuvent être utilisés pour optimiser les opérations de tri, en évitant les tris coûteux en mémoire. Enfin, vous avez appris à gérer vos index en les listant avec getIndexes() et en supprimant ceux qui ne sont pas utilisés avec dropIndex(). Ces compétences sont fondamentales pour construire des applications rapides et évolutives avec MongoDB.

