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

MongoDb :comment créer le bon index (composite) pour les données comportant de nombreux champs de recherche

Je vais essayer d'expliquer ce que cela signifie par exemple. Les index basés sur B-tree ne sont pas spécifiques à mongodb. En revanche, c'est un concept assez courant.

Ainsi, lorsque vous créez un index, vous montrez à la base de données un moyen plus simple de trouver quelque chose. Mais cet index est stocké quelque part avec un pointeur pointant vers un emplacement du document original. Cette information est ordonnée et vous pourriez la voir comme un arbre binaire qui a une très belle propriété :la recherche est réduite de O(n) (balayage linéaire) vers O(log(n)) . Ce qui est beaucoup plus rapide car chaque fois que nous réduisons notre espace de moitié (potentiellement, nous pouvons réduire le temps de 10 ^ 6 à 20 recherches). Par exemple, nous avons une grande collection avec le champ {a : some int, b: 'some other things'} et si on l'indexe par a, on se retrouve avec une autre structure de données qui est triée par a . Cela ressemble à ça (je ne veux pas dire par là qu'il s'agit d'une autre collection, c'est juste pour la démonstration) :

{a : 1, pointer: to the field with a = 1}, // if a is the smallest number in the starting collection
...
{a : 999, pointer: to the field with a = 990} // assuming that 999 is the biggest field

Donc, en ce moment, nous recherchons un champ a =18. Au lieu d'aller un par un à travers tous les éléments, nous prenons quelque chose au milieu et s'il est plus grand que 18, alors nous divisons la partie inférieure en deux et vérifions l'élément là . Nous continuons jusqu'à ce que nous trouvions a =18. Ensuite, nous regardons le pointeur et le connaissant, nous extrayons le champ d'origine.

La situation avec l'index composé est similaire (au lieu de commander par un élément, nous commandons par plusieurs). Par exemple, vous avez une collection :

{ "item": 5, "location": 1, "stock": 3, 'a lot of other fields' }  // was stored at position 5 on the disk
{ "item": 1, "location": 3, "stock": 1, 'a lot of other fields' }  // position 1 on the disk
{ "item": 2, "location": 5, "stock": 7, 'a lot of other fields' }  // position 3 on the disk
... huge amount of other data
{ "item": 1, "location": 1, "stock": 1, 'a lot of other fields' }  // position 9 on the disk
{ "item": 1, "location": 1, "stock": 2, 'a lot of other fields' }  // position 7 on the disk

et vous voulez un index { "item":1, "location":1, "stock":1 }. La table de recherche ressemblerait à ceci (une fois de plus - ce n'est pas une autre collection, c'est juste pour la démonstration) :

{ "item": 1, "location": 1, "stock": 1, pointer = 9 }
{ "item": 1, "location": 1, "stock": 2, pointer = 7 }
{ "item": 1, "location": 3, "stock": 1, pointer = 1 }
{ "item": 2, "location": 5, "stock": 7, pointer = 3 }
.. huge amount of other data (but not necessarily here. If item would be one it would be somewhere next to items 1)
{ "item": 5, "location": 1, "stock": 3, pointer = 5 }

Voyez qu'ici, tout est essentiellement trié par élément, puis par emplacement, puis par pointeur. De la même manière qu'avec un seul index, nous n'avons pas besoin de tout scanner. Si nous avons une requête qui recherche item = 2, location = 5 and stock = 7 nous pouvons identifier rapidement où les documents avec item = 2 sont, puis de la même manière, identifiez rapidement où parmi ces éléments l'élément avec location 5 et ainsi de suite.

Et maintenant une partie intéressante . De plus, nous avons créé un seul index (bien qu'il s'agisse d'un index composé, il s'agit toujours d'un index), nous pouvons l'utiliser pour trouver rapidement l'élément

  • uniquement par item . Vraiment, tout ce que nous devons faire n'est que la première étape. Il est donc inutile de créer un autre index {location :1} car il est déjà couvert par l'index composé.
  • nous pouvons également trouver rapidement uniquement par item and by location (nous n'avons besoin que de 2 étapes).

Cool 1 index mais nous aide de trois manières différentes. Mais attendez une minute :et si nous voulions rechercher par item and stock . Oh, il semble que nous puissions également accélérer cette requête. Nous pouvons dans log(n) trouver tous les éléments avec un élément spécifique et ... ici, nous devons nous arrêter - la magie est terminée. Nous devons les parcourir tous. Mais toujours assez bon.

Mais peut-il nous aider avec d'autres questions. Examinons une requête par location qui semble avoir déjà été commandé. Mais si vous le regardez, vous voyez que c'est un gâchis. Un au début puis un à la fin. Cela ne peut pas vous aider du tout.

J'espère que cela clarifie certaines choses :

  • pourquoi les index sont bons (réduire le temps de O(n) à potentiellement O(log(n))
  • pourquoi les index composés peuvent aider avec certaines requêtes, mais nous n'avons pas créé d'index sur ce champ particulier et nous n'aidons pas avec d'autres requêtes.
  • quels index sont couverts par l'index composé
  • pourquoi les index peuvent nuire (cela crée une structure de données supplémentaire qui doit être maintenue)

Et cela devrait indiquer une autre chose valable :l'index n'est pas une solution miracle . Vous ne pouvez pas accélérer toutes vos requêtes, il semble donc idiot de penser qu'en créant des index sur tous les champs, TOUT serait super rapide.