Vous souhaitez connaître le moyen le plus rapide de connaître les index d'une collection ou d'en créer facilement de nouveaux ? Essayez le gestionnaire indice : masquez et affichez les index d'un simple clic, éliminant ainsi le temps de reconstruction. Visualisez d'un coup d'œil la fréquence d'utilisation de vos index. Vous pouvez même comparer les index de différentes bases de données.
Que sont les index dans MongoDB et pourquoi en avons-nous besoin ?
Les index rendent l'interrogation des données plus efficace. Sans index, MongoDB effectue un balayage de la collection qui lit tous les documents de la collection pour déterminer si les données correspondent aux conditions spécifiées dans la requête. Les index limitent le nombre de documents lus par MongoDB et, en choisissant les bons index, vous pouvez améliorer les performances. Les index stockent la valeur d'un champ ou d'un ensemble de champs, classés en fonction de la valeur du champ.
Affichage du indice Directeur
Pour afficher les index d'une collection, localisez-la dans l'arborescence des connexions et développez-la. Vous pouvez également développer la section Index pour afficher les indice noms:

Pour afficher le indice Gestionnaire, double-cliquez sur l’entrée Index en haut de la section index.
Le indice Le gestionnaire affiche une liste de tous les index de la collection :

Pour afficher les champs 인덱싱된 et leur ordre de tri, cliquez sur la flèche du champ Nom:

indice taille
Pour des performances optimales, assurez-vous que tous les index de vos collections tiennent dans la RAM de votre serveur MongoDB afin d'éviter de les lire depuis le disque. Dans certains cas, les index ne stockent que les valeurs récentes en RAM ; pour plus d'informations, consultez la documentation MongoDB . Le champ Taille indique la taille de chaque index. indice dans la collection sélectionnée. Le total indice la taille (somme de tous les index) de la collection est affichée dans le coin inférieur droit de la indice Directeur.
indice usage
L'utilisation vous montre combien de fois un indice est utilisé depuis le indice a été créé ou depuis le dernier redémarrage du serveur.
indice Le gestionnaire affiche les informations d'utilisation uniquement si votre utilisateur dispose des privilèges pour la commande MongoDB $indexStats. Pour plus d'informations sur indice statistiques, voir la documentation MongoDB .
Si un indice n'est pas utilisé, vous devriez l'abandonner, pour éliminer les frais généraux associés à la maintenance du indice lorsque les valeurs des champs sont mises à jour et l'espace disque.
Ajout d'un indice
Dans l’arborescence de connexion, cliquez avec le bouton droit sur une collection, puis sélectionnez Ajouter indice .

Dans la boîte de dialogue Ajouter indice , saisissez le nom de votre indice dans la zone de nom d' indice . Si vous laissez cette zone vide, Studio 3T crée un indice par défaut. indice nom pour vous, basé sur les noms des champs que vous sélectionnez et le indice taper.
Ajoutez les champs obligatoires à votre indice Pour ce faire, sélectionnez le champ dans la liste Champs indexés , puis sélectionnez l'ordre de tri (1 asc ou -1 desc) ou le type de indice . Pour en savoir plus sur indice types et propriétés, voir Types indice MongoDB et Propriétés indice MongoDB . Cliquez sur Ajouter un champ .
Par défaut, MongoDB crée des index au premier plan, ce qui empêche toutes les opérations de lecture et d'écriture dans la base de données pendant que le indice construit. Cela donne des constructions compactes indice tailles et prend moins de temps à construire. Pour permettre aux opérations de lecture et d'écriture de continuer pendant la construction du indice , cochez la case « Créer en arrière-plan » . Cela produit un résultat moins compact. indice tailles et prend plus de temps à construire.
Cependant, au fil du temps, la taille convergera comme si vous aviez construit le indice au premier plan. Pour plus d'informations sur la création d'index, consultez la documentation MongoDB .
Lorsque vous avez terminé d'ajouter des champs à votre indice Cliquez sur Créer indice .
MongoDB indice types
Index à champ unique
Lorsque vous spécifiez des champs indexés, vous appliquez un ordre de tri pour chaque champ. Dans un champ unique indice , l'ordre de tri n'est pas important car MongoDB peut parcourir les données dans les deux sens.
Indices composés
Les index composés spécifient plusieurs champs 인덱싱된 . L'ordre dans lequel vous spécifiez les champs est important. MongoDB recommande de suivre la règle ESR (Equality, Search, Range) :
- ajoutez tout d'abord les champs pour lesquels des requêtes d'égalité sont exécutées, c'est-à-dire des correspondances exactes sur une seule valeur
- ensuite, ajouter des champs qui reflètent l'ordre de tri de la requête
- enfin, ajouter des champs pour les filtres de plage
Index à clés multiples
Les index multiclés sont utilisés pour les champs contenant des tableaux. Il suffit de spécifier le champ contenant le tableau et MongoDB crée automatiquement un index. indice clé pour chaque élément du tableau.
Index des textes
Les index textuels prennent en charge les recherches sur des champs de type chaîne ou tableau d'éléments de chaîne. Vous pouvez créer un texte. indice par collection. Un texte indice peut contenir plusieurs champs.
indice version : il existe trois versions, 3 étant la version par défaut.
Langue par défaut : la langue par défaut est l'anglais. La langue que vous sélectionnez détermine les règles utilisées pour analyser les racines des mots (suffixe) et définit les mots d'arrêt qui sont filtrés. Par exemple, en anglais, les suffixes comprennent -ing et -ed, et les mots vides comprennent the et a.
Remplacement de la langue: spécifier un nom de champ différent pour remplacer le champ de la langue.
Poids des champs: pour chaque champ 인덱싱된 , MongoDB multiplie le nombre de correspondances par le poids et additionne les résultats. MongoDB utilise cette somme pour calculer un score pour le document. Sélectionnez un champ dans la liste, indiquez son poids dans la case et cliquez sur Ajouter un champ. Le poids du champ par défaut est de 1.
Index de caractères génériques
Les index génériques prennent en charge les requêtes dont les noms de champs sont inconnus, par exemple dans les structures de données arbitraires définies par l'utilisateur et dont le schéma est dynamique. Un index non générique indice Prend en charge uniquement les requêtes portant sur les valeurs des structures de données définies par l'utilisateur. Les index génériques filtrent tous les champs correspondants.
Pour ajouter un caractère générique indice sur tous les champs de chaque document d'une collection, sélectionnez $** (tous les champs) dans la liste Champs indexés :

Index géospatiaux
Index 2d
Les index 2d sont utilisés pour les données stockées sous forme de points sur un plan bidimensionnel. Les index 2d sont destinés aux paires de coordonnées héritées de MongoDB 2.2 et antérieures. Lower bound (limite inférieure ) et Upper bound (limite supérieure ) vous permettent de spécifier une plage d'emplacement, au lieu des paramètres par défaut de -180 (inclus) pour la longitude et 180 (non inclus) pour la latitude. La précision des bits vous permet de définir la taille en bits des valeurs d'emplacement, jusqu'à 32 bits de précision. La valeur par défaut est de 26 bits, ce qui correspond à une précision d'environ 60 centimètres, lorsque l'on utilise la plage d'emplacements par défaut.
2d sphère
Les index 2d sphere supportent les requêtes qui calculent les géométries sur une sphère de type terrestre.
Botte de foin géo
Les index geoHaystack améliorent les performances des requêtes utilisant une géométrie plate. Ils étaient obsolètes dans MongoDB 4.4 et supprimés dans MongoDB 5.0. Ils créent des buckets de documents provenant d'une même zone géographique. Vous devez spécifier la taille du bucket . Par exemple, une taille de bucket de 5 crée un indice qui regroupe les valeurs de localisation situées à moins de 5 unités de la longitude et de la latitude données. La taille du bucket détermine également la granularité de la indice .
MongoDB indice propriétés
Index uniques
Les index uniques empêchent l'insertion de documents s'il existe déjà un document contenant cette valeur pour le champ 인덱싱된 .
Index clairsemés
Les index épars sautent les documents qui ne contiennent pas le champ 인덱싱된 , sauf si la valeur du champ est nulle. Les index épars ne contiennent pas tous les documents de la collection.
Index cachés
Les index masqués sont masqués du plan de requête. Cette option définit indice comme masqué lors de sa création. Vous pouvez définir le indice comme non caché dans le indice Gestionnaire, voir Masquer un indice pour plus d'informations.
Index TTL
Les index TTL sont des index à champ unique qui expirent les documents et demandent à MongoDB de supprimer les documents de la base de données après une période donnée. Le champ 인덱싱된 doit être de type date. Saisissez le délai d'expiration en secondes.
Index partiels
Les index partiels n'incluent que les documents qui répondent à une expression de filtre.
Index insensibles à la casse
Les index insensibles à la casse prennent en charge les requêtes qui ignorent la casse lors de la comparaison de chaînes. indice n'affecte pas les résultats d'une requête. Pour utiliser le indice , les requêtes doivent spécifier le même classement.
Vous définissez des index insensibles à la casse à l'aide du classement. Ce dernier vous permet de spécifier des règles spécifiques à la langue pour la comparaison de chaînes, comme les règles d'accentuation. Vous pouvez spécifier le classement lors de la collecte ou indice niveau. Si une collection a un classement défini, tous les index héritent de cette collection, sauf si vous spécifiez un classement personnalisé.
Pour spécifier un classement à indice Au niveau de la langue, cochez la case Utiliser un classement personnalisé . Le paramètre Locale est obligatoire et détermine les règles linguistiques. Définissez la valeur Strength sur 1 ou 2 pour un classement insensible à la casse. Tous les autres paramètres sont facultatifs et leurs valeurs par défaut varient selon les paramètres régionaux spécifiés. Pour plus d'informations sur les paramètres de classement, consultez la documentation MongoDB .
Laisser tomber un indice
Les index inutilisés ont un impact sur les performances d'une base de données car MongoDB doit maintenir le indice chaque fois que des documents sont insérés ou mis à jour. La colonne Utilisation dans le indice Le gestionnaire vous montre combien de fois un indice a été utilisé.
Avant de laisser tomber un indice , vous devriez tester dans quelle mesure le indice prend en charge les requêtes en les masquant . Si vous constatez une baisse de performances, affichez-les. indice , afin que les requêtes puissent l'utiliser à nouveau.
Vous ne pouvez pas supprimer le _id par défaut indice que MongoDB crée lorsque vous ajoutez une nouvelle collection.
Pour laisser tomber un indice , effectuez l'une des opérations suivantes :
- dans l'arborescence de connexion, faites un clic droit sur indice et sélectionnez Supprimer indice .
- dans l'arborescence de connexion, sélectionnez le indice et appuyez sur Ctrl + Retour arrière (Windows) ou fn + Suppr (Mac)
- sélectionnez le indice dans le indice Gestionnaire et cliquez sur le bouton Supprimer indice .
- faites un clic droit sur le indice dans le indice Gestionnaire et sélectionnez Supprimer indice .
En laisser tomber plus d'un indice , sélectionnez les index requis dans l'arborescence de connexion, cliquez avec le bouton droit et sélectionnez Supprimer les index .
Modification d'un indice
Modification d'un indice vous permet de modifier un existant indice , par exemple pour modifier les champs indexés. indice Le manager laisse tomber le indice pour vous et recrée le indice avec les modifications que vous avez spécifiées.
Pour éditer un indice , effectuez l’une des opérations suivantes pour ouvrir la boîte de dialogue Modifier indice :
- dans l'arborescence de connexion, faites un clic droit sur indice et sélectionnez Modifier indice .
- dans l'arborescence de connexion, sélectionnez le indice et appuyez sur la touche Entrée.
- sélectionnez le indice dans le indice Gestionnaire et cliquez sur le bouton Modifier indice .
- faites un clic droit sur le indice dans le indice Gestionnaire et sélectionnez Modifier indice .
Apportez les modifications requises et cliquez sur Supprimer et recréer indice .
Notez que si la seule modification que vous apportez à la indice est de cacher ou de dévoiler le indice , le indice Le gestionnaire n'a pas besoin de supprimer et de recréer le indice , vous cliquez donc sur Appliquer les modifications pour effectuer cette modification.
Affichage indice détails
Vous pouvez consulter une version en lecture seule du indice détails afin que vous ne modifiiez pas accidentellement les paramètres.
Pour afficher les détails d'un indice , effectuez l'une des opérations suivantes :
- sélectionnez le indice dans le indice Gestionnaire et cliquez sur le bouton Afficher les détails .
- faites un clic droit sur le indice dans le indice Gestionnaire et sélectionnez Afficher les détails .
Cacher un indice
Vous pouvez cacher un indice du plan de requête. Masquer un indice vous permet d'évaluer l'impact de l'abandon d'un indice . Cacher un indice vous évite d'avoir à abandonner le indice puis en le recréant. Vous pouvez comparer les performances des requêtes avec et sans indice en exécutant la requête avec le indice et puis cacher le indice et exécutez à nouveau la requête.
Lorsque vous cachez un indice , ses fonctionnalités s'appliquent toujours, par exemple, les index uniques appliquent toujours des contraintes uniques aux documents et les index TTL expirent toujours les documents. indice continue de consommer de l'espace disque et de la mémoire, donc si cela n'améliore pas les performances, vous devriez envisager d'abandonner le indice .
Les index cachés sont pris en charge à partir de la version 4.4 de MongoDB. Assurez-vous que la valeur de featureCompatibilityVersion est égale ou supérieure à 4.4.
Pour cacher un indice , effectuez l'une des opérations suivantes :
- dans l'arborescence de connexion, faites un clic droit sur indice et sélectionnez Masquer indice . Le indice est marqué comme caché.
- sélectionnez le indice dans le indice Gestionnaire et cliquez sur le bouton Masquer indice . La colonne Propriétés du indice Le gestionnaire montre que le indice est caché.
- faites un clic droit sur le indice dans le indice Gestionnaire et sélectionnez Masquer indice .
Pour afficher un indice , effectuez l'une des opérations suivantes :
- dans l'arborescence de connexion, faites un clic droit sur indice et sélectionnez Afficher indice .
- sélectionnez le indice dans le indice Gestionnaire et cliquez sur le bouton Masquer indice .
- faites un clic droit sur le indice dans le indice Gestionnaire et sélectionnez Afficher indice .
Copier un indice
Vous pouvez copier un indice d'une base de données et collez ses propriétés dans une autre base de données.
Pour copier un indice , effectuez l'une des opérations suivantes :
- dans l'arborescence de connexion, faites un clic droit sur indice et sélectionnez Copier indice .
- sélectionnez le indice dans le indice Gestionnaire et cliquez sur le bouton Copier .
- faites un clic droit sur le indice dans le indice Gestionnaire et sélectionnez Copier indice .
Pour coller le indice , dans l'arborescence de connexion, cliquez avec le bouton droit sur la collection cible et sélectionnez Coller indice .
Pour copier plus d'un indice Sélectionnez les index requis dans l'arborescence de connexion, faites un clic droit et sélectionnez « Copier les index » . Dans l'arborescence de connexion, faites un clic droit sur la collection cible et sélectionnez « Coller les index » .
Utiliser les index de MongoDB (Tutoriel)
Bien qu'il soit possible de stocker un grand nombre d'informations dans une base de données MongoDB, vous avez besoin d'une stratégie d'indexation efficace pour obtenir rapidement et efficacement les informations dont vous avez besoin.
Dans ce tutoriel, je vais passer en revue certaines des bases de l'utilisation des index MongoDB avec des requêtes simples, en laissant de côté les mises à jour et les insertions.
Il s'agit d'une approche pratique avec juste assez de théorie pour vous permettre d'essayer les exemples. L'intention est de permettre au lecteur de n'utiliser que le shell, bien que tout soit beaucoup plus facile dans l'interface graphique MongoDB que j'ai utilisée, Studio 3T.
Une introduction aux index de MongoDB
Lorsque MongoDB importe vos données dans une collection, il crée une clé primaire qui est renforcée par un index.
Mais il ne peut pas deviner les autres index dont vous aurez besoin, car il ne peut en aucun cas prédire le type de recherches, de tris et d'agrégations que vous voudrez effectuer sur ces données.
Il fournit simplement un identifiant unique pour chaque document de votre collection, qui est conservé dans tous les index ultérieurs. MongoDB n'autorise pas les tas. - des données non indexées liées simplement par des pointeurs avant et arrière.
MongoDB vous permet de créer des index supplémentaires qui sont similaires à ceux des bases de données relationnelles et qui nécessitent une certaine administration.
Comme pour les autres systèmes de base de données, il existe des index spéciaux pour les données éparses, pour la recherche dans le texte ou pour la sélection d'informations spatiales.
S'il existe un index approprié, une requête ou une mise à jour n'utilisera généralement qu'un seul index . Un index peut généralement améliorer les performances d'une opération sur les données, mais ce n'est pas toujours le cas.
Vous pouvez être tenté d'adopter l'approche du "saupoudrage", c'est-à-dire de créer de nombreux index différents, afin de s'assurer qu'il y en aura toujours un qui conviendra, mais l'inconvénient est que chaque index utilise des ressources et doit être maintenu par le système à chaque fois que les données changent.
Si vous avez trop d'index, ils finiront par dominer les pages de la mémoire et entraîneront des entrées/sorties excessives sur le disque. Il est préférable d'avoir un petit nombre d'index très efficaces.
Une petite collection est susceptible de tenir dans la mémoire cache, de sorte que le travail de création d'index et d'ajustement des requêtes ne semble pas avoir beaucoup d'influence sur les performances globales.
Toutefois, à mesure que la taille des documents augmente et que le nombre de documents s'accroît, ce travail se met en place. Votre base de données s'adaptera bien.
Création d'une base de données de test
Pour illustrer certaines des fonctions de base de l'index, nous allons charger 70 000 clients dans MongoDB à partir d'un fichier JSON. Chaque document contient le nom, l'adresse, le numéro de téléphone, les détails de la carte de crédit et les "notes de dossier" des clients. Ces dernières ont été générées à partir de nombres aléatoires.
Ce chargement peut être effectué soit à partir de Mongoimport, soit à partir d'un outil tel que Studio 3T.
Spécifier la collation dans les collections MongoDB
Avant de créer une collection, vous devez tenir compte de la collation, c'est-à-dire de la manière dont la recherche et le tri sont effectués (la collation n'est pas prise en charge avant MongoDB 3.4).
Lorsque vous voyez des chaînes de caractères dans l'ordre, voulez-vous que les minuscules soient triées après les majuscules ou votre tri doit-il ignorer la casse ? Considérez-vous qu'une valeur représentée par une chaîne de caractères est différente en fonction des majuscules ? Comment traiter les caractères accentués ? Par défaut, les collections ont une collation binaire qui n'est probablement pas ce qui est requis dans le monde du commerce.
Pour savoir quelle collation est utilisée, le cas échéant, pour votre collection, vous pouvez utiliser cette commande (ici pour notre collection "Clients").
db.getCollectionInfos({name: 'Customers'})

Cela montre que j'ai défini la collection Clients avec la collation "en".
Si je fais défiler la sortie du shell, je vois que tous les index MongoDB ont la même collation, ce qui est une bonne chose.
Malheureusement, vous ne pouvez pas modifier la collation d'une collection existant déjà. Vous devez créer la collection avant d'ajouter les données.
Voici comment créer une collection 'Customers' avec une collation anglaise. Dans Studio 3T, vous pouvez définir la collation via l'interface utilisateur et l'IntelliShell intégré.
Voici l'onglet Collation de la fenêtre "Ajouter une nouvelle collation" que l'on obtient en cliquant avec le bouton droit de la souris sur le nom de la base de données et en cliquant sur "Ajouter une nouvelle collation...".

Vous pouvez réaliser la même opération dans IntelliShell à l'aide de la commande :
db.createCollection("Customers", {collation:{locale:"en",strength:1}})

Vous pouvez également ajouter des informations de collation à toute recherche, tout tri ou toute comparaison de chaînes de caractères que vous effectuez.
D'après mon expérience, il est plus simple, plus sûr et plus clair de procéder à des modifications au niveau de la collection. Si le classement d'un indice ne correspond pas au classement de la recherche ou du tri que vous effectuez, alors MongoDB ne peut pas utiliser le indice .
Si vous importez un document, il est préférable que son ordre naturel soit pré-trié selon le classement spécifié, dans l'ordre de l'attribut le plus fréquemment indexé. Cela rend la clé primaire « groupée » dans le sens où indice peut avoir moins de blocs de pages à visiter pour chaque indice recherche de clé, et le système obtiendra un taux de réussite beaucoup plus élevé.
Comprendre le schéma
Une fois que nous avons chargé l'échantillon de données fictives, nous pouvons visualiser son schéma en examinant simplement le premier document
db.Customers.find({}).limit(1);
Dans Studio 3T, vous pouvez voir cela dans l'onglet Collection:

Index MongoDB pour les requêtes simples
Accélérer une requête très simple
Nous allons maintenant exécuter une simple requête dans notre base de données nouvellement créée afin de trouver tous les clients dont le nom de famille est "Johnston".
Nous souhaitons effectuer une projection sur, ou sélectionner, 'Prénom' et 'Nom de famille', triés par 'Nom de famille'. La ligne "_id" : NumberInt(0), signifie simplement "veuillez ne pas renvoyer l'ID".
use customers; db.Customers.find({ "Name.Last Name" : "Johnston" }, { "_id" : NumberInt(0), "Name.First Name" : NumberInt(1), "Name.Last Name" : NumberInt(1) }).sort({ "Name.Last Name" : NumberInt(1) });

Une fois que nous nous sommes assurés que la requête fournit le bon résultat, nous pouvons la modifier pour qu'elle fournisse les statistiques d'exécution.
use customers; use customers; db.Customers.find({ "Name.Last Name" : "Johnston" }, { "_id" : NumberInt(0), "Name.First Name" : NumberInt(1), "Name.Last Name" : NumberInt(1) }).sort({ "Name.Last Name" : NumberInt(1) }).explain("executionStats");
D'après les statistiques d'exécution de 'Explain', cela prend 59 Ms sur ma machine (ExecutionTimeMillis). Il s'agit d'un COLLSCAN, ce qui signifie qu'il n'y a pas d'index disponible et que Mongo doit donc parcourir toute la collection.
Ce n'est pas nécessairement une mauvaise chose dans le cas d'une collection raisonnablement petite, mais lorsque la taille augmente et que davantage d'utilisateurs accèdent aux données, la collection a moins de chances de tenir dans la mémoire paginée, et l'activité du disque s'accroît.
La base de données ne s'adaptera pas bien si elle est obligée d'effectuer un pourcentage élevé de COLLSCAN. C'est une bonne idée de minimiser les ressources utilisées par les requêtes fréquemment exécutées.
Il est évident que si un index permet de réduire le temps de traitement, il est probable qu'il s'agisse de Nom.Nom de famille.
Commençons donc par cela, en le transformant en index croissant, car nous voulons que le tri soit croissant :
db.Customers.createIndex( {"Name.Last Name" : 1 },{ name: "LastNameIndex"} )
Il faut maintenant 4 Ms sur ma machine (ExecutionTimeMillis). Il s'agit d'un IXSCAN (un balayage d'index pour obtenir les clés) suivi d'un FETCH (pour récupérer les documents).
Nous pouvons améliorer ce point car la requête doit obtenir le prénom.
Si nous ajoutons le Nom.Prénom dans le indice , alors le moteur de base de données peut utiliser la valeur dans le indice plutôt que de devoir effectuer l’étape supplémentaire consistant à le récupérer dans la base de données.
db.Customers.dropIndex("LastNameIndex") db.Customers.createIndex( { "Name.Last Name" : 1,"Name.First Name" : 1 }, { name: "LastNameCompoundIndex"} )
Grâce à ce système, la requête prend moins de 2 Ms.
Parce que l'index "couvre" la requête, MongoDB a pu faire correspondre les conditions de la requête et renvoyer les résultats en utilisant uniquement les clés de l'index, sans même avoir besoin d'examiner les documents de la collection pour renvoyer les résultats. (Si vous voyez une étape IXSCAN qui n'est pas un enfant d'une étape FETCH, dans le plan d'exécution, c'est que l'index "couvrait" la requête).
Vous remarquerez que notre tri était le type de tri ascendant le plus évident, de A à Z. Nous l'avons spécifié avec un 1 comme valeur pour le tri. Qu'en est-il si le résultat final doit être de Z à A (décroissant), spécifié par -1 ? Aucune différence n'est détectable avec ce petit ensemble de résultats.
Cela semble être un progrès. Mais que se passe-t-il si vous vous trompez d'index ? Cela peut poser des problèmes.
Si vous modifiez l’ordre des deux champs dans le indice pour que le Nom.Prénom vienne avant le Nom.Nom, le temps d'exécution monte jusqu'à 140 Ms, une augmentation énorme.
Cela semble bizarre parce que le indice a en fait ralenti l'exécution de sorte qu'elle prend plus du double du temps qu'elle prenait avec seulement le primaire par défaut indice (entre 40 et 60 Ms). MongoDB vérifie bien sûr les stratégies d'exécution possibles pour en choisir une bonne, mais à moins que vous n'ayez fourni une stratégie appropriée indice , il est difficile de choisir le bon.
Qu'avons-nous appris jusqu'à présent ?
Il semblerait que les requêtes simples bénéficient le plus des index qui sont impliqués dans les critères de sélection, et avec la même collation.
Dans notre exemple précédent, nous avons illustré une vérité générale sur les index MongoDB : si le premier champ de l'index indice ne fait pas partie des critères de sélection, il n'est pas utile d'exécuter la requête.
Accélérer les requêtes non-SARGables
Que se passe-t-il si nous avons deux critères, dont l'un implique une chaîne de caractères dans la valeur ?
use customers; db.Customers.find({ "Name.Last Name" : "Wiggins", "Addresses.Full Address" : /.*rutland.*/i });
Nous voulons trouver un client appelé Wiggins qui habite à Rutland. Il faut 50 Ms sans aucun indice à l'appui.
Si nous excluons le nom de la recherche, le temps d'exécution double.
use customers; db.Customers.find({ "Addresses.Full Address" : /.*rutland.*/i });
Si nous introduisons maintenant un composé indice qui commence par le nom puis ajoute l'adresse, nous constatons que la requête a été si rapide que 0 Ms a été enregistrée.
C'est parce que le indice J'ai permis à MongoDB de trouver uniquement ces 52 Wiggins dans la base de données et d'effectuer la recherche uniquement sur ces adresses. Cela semble suffisant !
Que se passe-t-il si nous inversons les deux critères ? De manière surprenante, le rapport "explain" fait état de 72 Ms.
Il s'agit de deux critères valables spécifiés dans la requête, mais si le mauvais critère est utilisé, la requête est plus qu'inutile, à hauteur de 20 Ms.
La raison de cette différence est évidente. L'index peut empêcher un balayage de toutes les données, mais il ne peut pas améliorer la recherche puisqu'il s'agit d'une expression régulière.
Il existe deux principes généraux.
Une recherche complexe doit réduire autant que possible les candidats à la sélection avec le premier élément de la liste d'index. La "cardinalité" est le terme utilisé pour ce type de sélectivité. Un champ à faible cardinalité, tel que le sexe, est beaucoup moins sélectif que le nom de famille.
Dans notre exemple, le nom de famille est suffisamment sélectif pour être le choix évident pour le premier champ répertorié dans un indice , mais peu de questions sont aussi évidentes.
La recherche proposée par le premier champ d'un index utilisable doit être SARGable. Il s'agit d'un raccourci pour dire que le champ de l'index doit être SearchARGumentable.
Dans le cas de la recherche du mot "rutland", le terme de recherche n'était pas directement lié au contenu de l'index et à l'ordre de tri de l'index.
Nous avons pu l'utiliser efficacement uniquement parce que nous avons utilisé l'ordre de l'index pour persuader MongoDB d'adopter la meilleure stratégie pour trouver les vingt "Wiggins" potentiels dans la base de données, puis en utilisant la copie de l'adresse complète dans l'index plutôt que le document lui-même.
Il peut alors rechercher ces vingt adresses complètes très rapidement sans même avoir à extraire les données des vingt documents. Enfin, grâce à la clé primaire contenue dans l'index, il peut très rapidement extraire le bon document de la collection.
Inclure un tableau intégré dans une recherche
Essayons une requête un peu plus complexe.
Nous voulons effectuer une recherche à partir du nom de famille et de l'adresse électronique du client.
Notre collection de documents permet à notre "client" d'avoir une ou plusieurs adresses électroniques. Celles-ci se trouvent dans un tableau intégré.
Nous voulons simplement trouver une personne portant un nom de famille particulier, "Barker" dans notre exemple, et une certaine adresse électronique, "[email protected]" dans notre exemple.
Nous voulons renvoyer uniquement l'adresse électronique correspondante et les détails qui vont avec (quand elle a été enregistrée et quand elle est devenue invalide). Nous allons exécuter cette commande à partir du shell et examiner les statistiques d'exécution.
db.Customers.find({ "Name.Last Name" : "Barker", "EmailAddresses.EmailAddress" : "[email protected]" }, { "_id" : NumberInt(0), "EmailAddresses.$.EmailAddress" : NumberInt(1), "Full Name" : NumberInt(1) });
Ce qui donne :
{ "Full Name" : "Mr Cassie Gena Barker J.D.", "EmailAddresses" : [ { "EmailAddress" : "[email protected]", "StartDate" : "2016-05-02", "EndDate" : "2018-01-25" } ] }
Cela nous indique que Cassie Barker a eu l'adresse électronique [email protected] du 11 janvier 2016 au 25 janvier 2018. L'exécution de la requête a pris 240 ms car il n'y avait pas d'index utile (les 40000 documents ont été examinés dans un COLLSCAN).
Nous pouvons créer un index pour faciliter cette tâche :
db.Customers.createIndex( { "Name.Last Name" : 1 },{ name: "Nad"} );
Ce indice réduit le temps d'exécution à 6 ms.
Le Nad indice c'était le seul disponible pour la collection qui se trouvait uniquement dans le champ Nom.Nom de famille .
Pour l'étape d'entrée, la stratégie IXSCAN a été utilisée et a permis d'obtenir très rapidement 33 documents correspondants, en avançant dans le processus.
Il a ensuite filtré les documents correspondants pour récupérer le tableau EmailAddresses pour l'adresse qui a ensuite été renvoyée dans l'étape de projection. Au total, 3 Ms ont été utilisés, alors que 70 Ms ont été nécessaires.
L'ajout d'autres champs dans l'index n'a pas eu d'effet perceptible. C'est le premier champ de l'index qui détermine le succès.
Et si nous voulions simplement savoir qui utilise une adresse électronique particulière ?
db.Customers.find({ "EmailAddresses.EmailAddress" : "[email protected]" }, { "_id" : NumberInt(0), "EmailAddresses.$.EmailAddress" : NumberInt(1), "Full Name" : NumberInt(1) });
Ici, un index sur le champ emailAddress fait des merveilles. Sans index approprié, il effectue un COLLSCAN qui prend environ 70 Ms sur mon serveur de développement.
Avec un index...
db.Customers.createIndex( { "EmailAddresses.EmailAddress" : 1 },{ name: "AddressIndex"} )
... le délai est déjà trop court pour être mesuré.
Vous aurez remarqué que, pour indexer un champ contenant un tableau, MongoDB crée une clé d'indexation pour chaque élément du tableau.
Nous pourrions être encore plus rapides si nous supposions que les adresses électroniques sont uniques (ce n'est pas le cas dans ces données fabriquées; et dans la vie réelle, c'est une supposition dangereuse).
Nous pouvons également utiliser le indice pour « couvrir » la récupération du champ « Nom complet », afin que MongoDB puisse récupérer cette valeur à partir du indice plutôt que de le récupérer dans la base de données, mais la proportion de temps gagné sera faible.
L'une des raisons pour lesquelles les récupérations d'index fonctionnent si bien est qu'elles ont tendance à obtenir de bien meilleurs taux de réussite dans le cache que les balayages de collections complètes. Toutefois, si l'ensemble de la collection peut tenir dans le cache, l'analyse de la collection aura des performances plus proches de celles de l'index.
Utiliser les agrégations
Voyons quels sont les noms les plus populaires dans notre liste de clients, en utilisant une agrégation. Nous allons créer un index à partir de "Nom.Nom de famille".
db.Customers.aggregate({$project :{"Name.Last Name": 1}}, {$group :{_id: "$Name.Last Name", count : {$sum: 1}}}, {$sort : {count : -1}}, {$limit:10} );
Nous avons donc beaucoup de membres de la famille Snyder dans notre top 10:
{ "_id" : "Snyder", "count" : 83 } { "_id" : "Baird", "count" : 81 } { "_id" : "Evans", "count" : 81 } { "_id" : "Andrade", "count" : 81 } { "_id" : "Woods", "count" : 80 } { "_id" : "Burton", "count" : 79 } { "_id" : "Ellis", "count" : 77 } { "_id" : "Lutz", "count" : 77 } { "_id" : "Wolfe", "count" : 77 } { "_id" : "Knox", "count" : 77 }
Cela n'a pris que 8 Ms malgré un COLLSCAN, car toute la base de données a pu être conservée dans la mémoire cache.
Il utilise le même plan de requête même si vous effectuez l'agrégation sur un champ non indexé. (Elisha, Eric, Kim et Lee sont les prénoms les plus populaires !)
Je me demande quels sont les prénoms qui ont tendance à attirer le plus de notes sur leur dossier ?
db.Customers.aggregate( {$group: {_id: "$Name.First Name", NoOfNotes: {$avg: {$size: "$Notes"}}}}, {$sort : {NoOfNotes : -1}}, {$limit:10} );
Dans mes données fictives, ce sont les personnes appelées Charisse qui obtiennent le plus de notes. Ici, nous savons qu'un COLLSCAN est inévitable car le nombre de notes changera dans un système réel. Certaines bases de données permettent d'indexer les colonnes calculées, mais cela n'est pas utile dans le cas présent.
{ "_id" : "Charisse", "NoOfNotes" : 1.793103448275862 } { "_id" : "Marian", "NoOfNotes" : 1.72 } { "_id" : "Consuelo", "NoOfNotes" : 1.696969696969697 } { "_id" : "Lilia", "NoOfNotes" : 1.6666666666666667 } { "_id" : "Josephine", "NoOfNotes" : 1.65625 } { "_id" : "Willie", "NoOfNotes" : 1.6486486486486487 } { "_id" : "Charlton", "NoOfNotes" : 1.6458333333333333 } { "_id" : "Kristi", "NoOfNotes" : 1.6451612903225807 } { "_id" : "Cora", "NoOfNotes" : 1.64 } { "_id" : "Dominic", "NoOfNotes" : 1.6363636363636365 }
Les performances des agrégations peuvent être améliorées par un index car elles peuvent couvrir l'agrégation. Seuls les opérateurs de pipeline $match et $sort peuvent tirer parti d'un index directement, et uniquement s'ils interviennent au début du pipeline.
Le générateur de données SQL a été utilisé pour générer les données de test dans ce tutoriel.
Conclusions
- Lorsqu'on élabore une stratégie d'indexation pour MongoDB, on constate qu'un certain nombre de facteurs doivent être pris en compte, tels que la structure des données, le modèle d'utilisation et la configuration des serveurs de base de données.
- MongoDB n'utilise généralement qu'un seul index lors de l'exécution d'une requête, à la fois pour la recherche et le tri ; et s'il a le choix de la stratégie, il échantillonne les meilleurs index candidats.
- La plupart des collections de données ont des candidats assez performants pour les index, susceptibles de différencier clairement les documents de la collection, et susceptibles d'être fréquents dans les recherches.
- C'est une bonne idée d'être parcimonieux avec les index parce qu'ils constituent un petit coût en termes de ressources. Un autre danger est d'oublier ce qui existe déjà, bien qu'il ne soit heureusement pas possible de créer des index en double dans MongoDB.
- Il est toujours possible de créer plusieurs index composés très proches dans leur constitution. Si un indice n'est pas utilisé, il est préférable de l'abandonner.
- Les index composés sont très efficaces pour soutenir les requêtes. Ils utilisent le premier champ pour effectuer la recherche et utilisent ensuite les valeurs des autres champs pour renvoyer les résultats, plutôt que de devoir récupérer les valeurs dans les documents. Ils prennent également en charge les tris qui utilisent plus d'un champ, à condition qu'ils soient effectués dans le bon ordre.
- Pour que les index soient efficaces pour les comparaisons de chaînes de caractères, ils doivent utiliser la même collation.
- Il est utile de surveiller les performances des requêtes. En plus d'utiliser les valeurs renvoyées par explain(), il est utile de chronométrer les requêtes et de vérifier les requêtes de longue durée en activant le profilage et en examinant les requêtes les plus lentes. Il est en fait étonnamment facile de modifier la vitesse de ces requêtes en fournissant le bon index.
FAQ sur les index MongoDB
Les index ne ralentissent pas les requêtes MongoDB. Cependant, lorsqu'un document est créé, mis à jour ou supprimé, les index associés doivent également être mis à jour, ce qui a un impact sur les performances d'écriture.
Vous devriez éviter l'indexation dans MongoDB lorsque vous avez une petite collection ou lorsque vous avez une collection qui n'est pas fréquemment interrogée.
Parce que MongoDB crée un fichier pour chaque indice Un nombre excessif d'index peut impacter les performances. Au démarrage, le moteur de stockage MongoDB ouvre tous les fichiers ; un nombre excessif d'index peut donc impacter les performances.
Double-cliquez sur la section Index de l'arborescence des connexions correspondant aux collections à comparer afin d'afficher deux onglets du Gestionnaire indice . Faites un clic droit en haut de l'un des onglets et sélectionnez « Séparer verticalement » . Les onglets s'affichent côte à côte pour vous permettre de comparer les index des deux bases de données.
Exécutez votre requête dans l'onglet Collections et ouvrez l'onglet Expliquer pour visualiser le traitement de la requête par MongoDB. Si la requête utilise un indice , une étape d'analyse indice s'affiche ; sinon, une étape d'analyse de collection s'affiche . Pour plus d'informations sur l'utilisation de l'onglet Expliquer, consultez l'article de la base de connaissances « Expliquer visuellement | MongoDB Explain, Visualisé » .
Recherchez la collection dans l'arborescence de connexion et double-cliquez sur la section Index pour ouvrir le indice Gestionnaire. Le indice Le gestionnaire affiche les informations de taille pour chaque indice sur la collection.
Recherchez la collection dans l'arborescence des connexions. Les index sont répertoriés dans la section Index, sous le nom de la collection. Double-cliquez sur un indice pour afficher une version en lecture seule de ses détails. Les détails de taille et d'utilisation sont affichés dans le indice Onglet Gestionnaire dans l'onglet Collections.
Lorsque MongoDB crée un indice , il verrouille temporairement la collection, empêchant ainsi toute opération de lecture et d'écriture sur les données de cette collection. MongoDB crée les métadonnées indice , une table temporaire de clés et une table temporaire de violations de contraintes. Le verrou de la collection est ensuite rétrogradé et les opérations de lecture et d'écriture sont autorisées périodiquement. MongoDB analyse les documents de la collection et écrit dans les tables temporaires. Lors de la création de l' indice , MongoDB verrouille la collection de manière exclusive à plusieurs étapes. Pour plus de détails sur le processus de création, consultez la documentation MongoDB . Une fois l' indice créé, MongoDB met à jour les métadonnées indice et libère le verrou.
Dans un environnement de production, si votre collection a une charge d'écriture importante, vous devriez envisager de créer votre indice pendant les périodes d'exploitation réduite, par exemple pendant les périodes de maintenance, afin que les performances ne soient pas affectées et indice le temps de construction est plus court.
Lorsque vous créez un indice dans MongoDB, le chiffre 1 spécifie que vous souhaitez créer le indice par ordre croissant. Pour créer un indice dans l'ordre décroissant, vous utilisez -1.
En savoir plus sur les index MongoDB
Vous souhaitez en savoir plus sur les index MongoDB ? Consultez ces articles de la base de connaissances :
Comment optimiser les requêtes MongoDB en utilisant find() et les index
Comment utiliser le profileur MongoDB et explain() pour trouver les requêtes lentes
Visual Explain | MongoDB Explain, Visualized
Cet article a été initialement publié par Phil Factor et a été mis à jour depuis.