MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Index composés MongoDB - L'ordre de tri est-il important ?

Vous pouvez considérer l'index à champ unique MongoDB comme un tableau, avec des pointeurs vers des emplacements de documents. Par exemple, si vous avez une collection avec (notez que la séquence est volontairement dans le désordre) :

[collection]
1: {a:3, b:2}
2: {a:1, b:2}
3: {a:2, b:1}
4: {a:1, b:1}
5: {a:2, b:2}

Index à champ unique

Maintenant, si vous le faites :

db.collection.createIndex({a:1})

L'index ressemble approximativement à :

[index a:1]
1: {a:1} --> 2, 4
2: {a:2} --> 3, 5
3: {a:3} --> 1

Notez trois choses importantes :

  • Il est trié par a croissant
  • Chaque entrée pointe vers l'emplacement où se trouvent les documents pertinents
  • L'index n'enregistre que les valeurs du a champ. Le b le champ n'existe pas du tout dans l'index

Donc, si vous faites une requête comme :

db.collection.find().sort({a:1})

Tout ce qu'il a à faire est de parcourir l'index de haut en bas, en récupérant et en sortant le document pointé par les entrées. Notez que vous pouvez également parcourir l'index à partir du bas, par exemple :

db.collection.find().sort({a:-1})

et la seule différence est que vous parcourez l'index en sens inverse.

Parce que b n'est pas du tout dans l'index, vous ne pouvez pas utiliser l'index lorsque vous interrogez quoi que ce soit sur b .

Indice composé

Dans un index composé, par exemple :

db.collection.createIndex({a:1, b:1})

Cela signifie que vous voulez trier par a d'abord, puis trier par b . L'index ressemblerait à :

[index a:1, b:1]
1: {a:1, b:1} --> 4
2: {a:1, b:2} --> 2
3: {a:2, b:1} --> 3
4: {a:2, b:2} --> 5
5: {a:3, b:2} --> 1

Notez que :

  • L'index est trié à partir de a
  • Dans chaque a vous avez un b trié
  • Vous avez 5 entrées d'index contre seulement trois dans l'exemple à champ unique précédent

En utilisant cet index, vous pouvez faire une requête comme :

db.collection.find({a:2}).sort({b:1})

Il peut facilement trouver où a:2 puis faites défiler l'index vers l'avant. Compte tenu de cet index, vous ne pouvez pas faire :

db.collection.find().sort({b:1})
db.collection.find({b:1})

Dans les deux requêtes, vous ne pouvez pas facilement trouver b car il est réparti sur tout l'index (c'est-à-dire pas dans des entrées contiguës). Cependant, vous pouvez faire :

db.collection.find({a:2}).sort({b:-1})

puisque vous pouvez essentiellement trouver où le a:2 sont, et marchez sur le b entrées vers l'arrière.

Modifier :clarification de la question de @marcospgp en commentaire :

La possibilité d'utiliser l'index {a:1, b:1} pour satisfaire find({a:2}).sort({b:-1}) en fait un sens si vous le voyez du point de vue d'un tableau trié. Par exemple, l'index {a:1, b:1} peut être considéré comme :

a | b
--|--
1 | 1
1 | 2
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2

trouver({a:2}).sort({b:1})

L'indice {a:1, b:1} signifie sort by a, then within each a, sort the b values . Si vous faites ensuite un find({a:2}).sort({b:1}) , l'index sait où tous les a=2 sommes. Dans ce bloc de a=2 , le b serait trié par ordre croissant (selon la spécification d'index), de sorte que la requête find({a:2}).sort({b:1}) peut être satisfait par :

a | b
--|--
1 | 1
1 | 2
2 | 1 <-- walk this block forward to satisfy
2 | 2 <-- find({a:2}).sort({b:1})
2 | 3 <--
3 | 1
3 | 2

trouver({a:2}).sort({b:-1})

Étant donné que l'index peut être déplacé vers l'avant ou vers l'arrière, une procédure similaire a été suivie, avec une petite torsion à la fin :

a | b
--|--
1 | 1
1 | 2
2 | 1  <-- walk this block backward to satisfy
2 | 2  <-- find({a:2}).sort({b:-1})
2 | 3  <--
3 | 1
3 | 2

Le fait que l'index puisse être avancé ou reculé est le point clé qui active la requête find({a:2}).sort({b:-1}) pouvoir utiliser l'index {a:1, b:1} .

Explication du planificateur de requêtes

Vous pouvez voir ce que le planificateur de requêtes prévoit en utilisant db.collection.explain().find(....) . Fondamentalement, si vous voyez une stage de COLLSCAN , aucun index n'a été utilisé ou ne peut être utilisé pour la requête. Voir expliquer les résultats pour plus de détails sur la sortie de la commande.