web-dev-qa-db-fra.com

Pourquoi et quand est-il nécessaire de reconstruire des index dans MongoDB?

Travaille avec MongoDB depuis un certain temps et aujourd'hui j'ai eu un doute en discutant avec un collègue.

Le fait est que lorsque vous créez un index dans MongoDB, la collection est traitée et l'index est construit.

L'index est mis à jour lors de l'insertion et de la suppression de documents, je ne vois donc pas vraiment la nécessité d'exécuter une opération de reconstruction d'index (qui supprime l'index puis le reconstruit).

Selon la documentation MongoDB:

Normalement, MongoDB compacte les index lors des mises à jour de routine. Pour la plupart des utilisateurs, la commande reIndex n'est pas nécessaire. Cependant, il peut être utile de l'exécuter si la taille de la collection a changé de manière significative ou si les index consomment une quantité disproportionnée d'espace disque.

Quelqu'un a-t-il eu besoin d'exécuter une opération de reconstruction d'index qui en valait la peine?

24
javierfdezg

Selon la documentation MongoDB, il n'est généralement pas nécessaire de reconstruire régulièrement les index.

[~ # ~] note [~ # ~] : Tout conseil sur le stockage devient plus intéressant avec MongoDB 3.0+, qui a introduit un enfichable API du moteur de stockage . Mes commentaires ci-dessous font spécifiquement référence au moteur de stockage MMAP par défaut dans MongoDB 3.0 et versions antérieures. WiredTiger et d'autres moteurs de stockage ont différentes implémentations de stockage pour les données et les index.

Il peut être avantageux de reconstruire un index avec le moteur de stockage MMAP si:

  • Un index consomme plus d'espace que prévu par rapport aux données. Remarque: vous devez surveiller les données historiques et la taille de l'index pour disposer d'une base de comparaison.

  • Vous souhaitez migrer d'un ancien format d'index vers un nouveau. Si une réindexation est souhaitable, cela sera mentionné dans les notes de mise à niveau. Par exemple, MongoDB 2.0 a introduit une importante amélioration des performances d'index de sorte que les notes de version incluent une réindexation suggérée au format v2.0 après la mise à niveau. De même, MongoDB 2.6 a introduit 2dsphere (v2.0) index qui ont un comportement par défaut différent (clairsemé par défaut). Les index existants ne sont pas reconstruits après les mises à niveau de la version d'index; le choix de si/quand mettre à niveau est laissé à l'administrateur de la base de données.

  • Vous avez modifié le _id format pour une collection vers ou depuis une clé à augmentation monotone (par exemple, ObjectID) vers une valeur aléatoire. C'est un peu ésotérique, mais il y a une optimisation d'index qui divise les compartiments de l'arbre b 90/10 (au lieu de 50/50) si vous insérez _ids qui augmentent toujours (ref: SERVER-98 ). Si la nature de votre _ids change considérablement, il peut être possible de construire un arbre b plus efficace avec un ré-index.

Pour plus d'informations sur le comportement général de l'arbre B, voir: Wikipedia: B-tree

Visualisation de l'utilisation des index

Si vous êtes vraiment curieux de creuser un peu plus dans les éléments internes de l'index, vous pouvez essayer quelques commandes/outils expérimentaux. Je m'attends à ce que ceux-ci soient limités à MongoDB 2.4 et 2.6 uniquement:

11
Stennie

Bien que je ne connaisse pas les raisons techniques exactes pourquoi, dans MongoDB, je peux faire quelques hypothèses à ce sujet, sur la base de ce que je sais sur l'indexation à partir d'autres systèmes et sur la base de la documentation que vous avez citée.

L'idée générale d'un index

Lors du passage d'un document à l'autre, dans la collection complète de documents, il y a beaucoup de temps et d'efforts gaspillés pour ignorer toutes les données qui n'ont pas besoin d'être traitées. Si vous recherchez un document avec l'ID "1234", le fait de devoir parcourir 100K + de chaque document le ralentit

Plutôt que d'avoir à parcourir tout le contenu de chaque document de la collection (déplacement physique des têtes de lecture du disque, etc.), un index rend cela rapide. Il s'agit essentiellement d'une paire clé/valeur qui vous donne l'ID et l'emplacement de ce document. MongoDB peut rapidement parcourir tous les identifiants de l'index, trouver les emplacements des documents dont il a besoin et les charger directement.

Allocation de la taille de fichier pour un index

Les index occupent de l'espace disque car ils sont essentiellement une paire clé/valeur stockée dans un emplacement beaucoup plus petit. Si vous avez une très grande collection (grand nombre d'éléments dans la collection), alors votre index augmente en taille.

La plupart des systèmes d'exploitation allouent des morceaux d'espace disque dans certaines tailles de bloc. La plupart des bases de données allouent également de l'espace disque en gros morceaux, selon les besoins.

Au lieu d'augmenter 100 Ko de taille de fichier lorsque 100 Ko de documents sont ajoutés, MongoDB augmentera probablement 1 Mo ou peut-être 10 Mo ou quelque chose - je ne sais pas quelle est la taille de croissance réelle. Dans SQL Server, vous pouvez lui dire à quelle vitesse croître, et MongoDB a probablement quelque chose comme ça.

La croissance en morceaux donne la possibilité de "faire croître" les documents dans l'espace plus rapidement car la base de données n'a pas besoin de se développer constamment. Si la base de données dispose désormais de 10 Mo d'espace déjà alloué, elle peut simplement utiliser cet espace. Il n'a pas besoin de continuer à développer le fichier pour chaque document. Il suffit d'écrire les données dans le fichier.

Cela est probablement vrai pour les collections et les index des collections - tout ce qui est stocké sur le disque.

Reconstruction de la taille du fichier et de l'index

Lorsqu'une grande collection contient de nombreux documents ajoutés et supprimés, l'index devient fragmenté. les clés d'index peuvent ne pas être en ordre car il y avait de la place au milieu du fichier d'index et pas à la fin, lorsque l'index devait être construit. Les clés d'index peuvent également avoir beaucoup d'espace entre elles.

S'il y a 10 000 éléments dans l'index et que # 10 001 doit être inséré, il peut être inséré au milieu du fichier d'index. Maintenant, l'index doit se reconstruire pour tout remettre en ordre. Cela implique de déplacer beaucoup de données, de faire de la place à la fin du fichier et de mettre l'article # 10,001 à la fin.

Si l'index est constamment battu - beaucoup de choses supprimées et ajoutées - il est probablement plus rapide de simplement augmenter la taille du fichier d'index et de toujours mettre des choses à la fin. cela est rapide pour créer l'index, mais laisse des trous vides dans le fichier où les anciennes choses ont été supprimées.

Si le fichier d'index a un espace vide où se trouvaient les éléments supprimés, c'est un effort inutile lors de la lecture de l'index. Le fichier d'index a plus de mouvement que nécessaire pour accéder à l'élément suivant de l'index. Ainsi, l'index se répare lui-même ... ce qui peut prendre du temps pour de très grandes collections ou des modifications très importantes d'une collection.

Reconstruire pour un gros fichier d'index

Il peut falloir beaucoup d'accès au disque et d'opérations d'E/S pour compacter correctement le fichier d'index à une taille raisonnable, avec tout en ordre. Déplacez les objets déplacés vers l'emplacement temporaire, libérez de l'espace au bon endroit, déplacez-les vers l'arrière. Oh au fait, pour libérer de l'espace, vous avez dû déplacer d'autres objets vers l'emplacement temporaire. C'est récursif et lourd.

Par conséquent, si vous avez un très grand nombre d'éléments dans une collection et que cette collection a des éléments ajoutés et supprimés régulièrement, l'index peut avoir besoin d'être reconstruit à partir de zéro. Cela effacerait le fichier d'index actuel et le reconstruirait à partir de zéro - ce qui sera probablement plus rapide que d'essayer de faire des milliers de mouvements à l'intérieur du fichier existant. Plutôt que de déplacer des objets, il les écrit simplement de manière séquentielle, à partir de zéro.

Grand changement dans la taille de la collection

Compte tenu de tout ce que je suppose ci-dessus, un grand changement dans la taille de la collection entraînerait ce genre de raclée. Si vous avez 10 000 documents dans la collection et que vous en supprimez 8 000 ... eh bien, vous avez maintenant un espace vide dans votre fichier d'index où se trouvaient les 8 000 éléments. MongoDB doit déplacer les 2 000 éléments restants dans le fichier physique pour le reconstruire sous une forme compacte.

Au lieu d'attendre que 8 000 espaces vides soient nettoyés, il pourrait être plus rapide de reconstruire à partir de zéro avec les 2 000 articles restants.

Conclusion? Peut être?

Ainsi, la documentation que vous avez citée traitera probablement des besoins de "big data" ou de collections et d'index très riches.

Gardez également à l'esprit que je fais une supposition éclairée basée sur ce que je sais sur l'indexation, l'allocation de disque, la fragmentation des fichiers, etc.

Je suppose que "la plupart des utilisateurs" dans la documentation, signifie que 99,9% ou plus des collections mongodb n'ont pas à s'en soucier.

Cas spécifique de MongoDB

Selon la documentation MongoDB:

La méthode remove () ne supprime pas les index

Donc, si vous supprimez des documents d'une collection, vous perdez de l'espace disque, sauf si vous reconstruisez l'index de cette collection.

3
Derick Bailey