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

Indice composé triple de Mongo

résultat / tl;dr : Indice b peut être 'ignoré' si a et c sont interrogés pour l'égalité ou l'inégalité, mais pas, par exemple, pour les tris sur c .

C'est une très bonne question. Malheureusement, je n'ai rien trouvé qui réponde avec autorité à cela plus en détail. Je pense que les performances de ces requêtes se sont améliorées au cours des dernières années, donc je ne ferais pas confiance aux anciens documents sur le sujet.

Le tout est assez compliqué car cela dépend de la sélectivité de vos index et si vous interrogez pour l'égalité, l'inégalité et/ou le tri, donc explain() est votre seul ami, mais voici certaines choses que j'ai trouvées :

Mise en garde :Ce qui vient maintenant est un mélange de résultats expérimentaux, de raisonnements et de suppositions. Je pousse peut-être trop loin l'analogie de Kyle, et je peux même me tromper complètement (et pas de chance, car les résultats de mes tests correspondent vaguement à mon raisonnement).

Il est clair que l'indice de A peut être utilisé, ce qui, selon la sélectivité de A, est certainement très utile. 'Skipping' B peut être délicat, ou non. Gardons cela similaire à l'exemple du livre de recettes de Kyle :

French
    Beef
        ...
    Chicken
        Coq au Vin
        Roasted Chicken
    Lamb
        ...
    ...

Si vous me demandez maintenant de trouver un plat français appelé "Chateaubriand", je peux utiliser l'index A et, parce que je ne connais pas l'ingrédient, devra scanner tous les plats en A . Par contre, je sais que la liste des plats de chaque catégorie est triée par l'index C , je n'aurai donc qu'à rechercher les chaînes commençant par, disons, "Cha" dans chaque liste d'ingrédients. S'il y a 50 ingrédients, j'aurai besoin de 50 recherches au lieu d'une seule, mais c'est bien mieux que de devoir scanner tous les plats français !

Dans mes expériences, le nombre était beaucoup plus petit que le nombre de valeurs distinctes dans b :il n'a jamais semblé dépasser 2. Cependant, je n'ai testé cela qu'avec une seule collection, et cela a probablement à voir avec la sélectivité du b -index.

Si vous me demandiez de vous donner une liste alphabétique de tous les plats français , cependant, j'aurais des ennuis . Maintenant l'index sur C est sans valeur, je devrais fusionner-trier toutes ces listes d'index. Je devrai scanner chaque élément pour le faire.

Cela se reflète dans mes tests. Voici quelques résultats simplifiés. La collection d'origine a des dates, des entiers et des chaînes, mais je voulais garder les choses simples, donc c'est maintenant tout entier.

Essentiellement, il n'y a que deux classes de requêtes :celles où nscanned <=2 * limit , et ceux qui doivent numériser l'intégralité de la collection (documents de 120 000). L'indice est {a, b, c} :

// fast (range query on c while skipping b)
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }});
// slow (sorting)
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}).sort({ "c" : -1});
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}).sort({ "b" : -1}); 

// fast (can sort on c if b included in the query)
> db.Test.find({"a" : 43, "b" : 7887, "c" : { $lte : 45454 }}).sort({ "c" : -1});

// fast (older tutorials claim this is slow)
> db.Test.find({"a" : {$gte : 43}, "c" : { $lte : 45454 }});

Votre kilométrage variera.