MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Mongo Triple Compound Index

Fazit / tl;dr: Index b kann 'übersprungen' werden, wenn a und c werden auf Gleichheit oder Ungleichheit abgefragt, nicht aber zB bei Sortierungen auf c .

Das ist eine sehr gute Frage. Leider konnte ich nichts finden, was dies ausführlicher beantwortet. Ich glaube, dass sich die Leistung solcher Abfragen in den letzten Jahren verbessert hat, daher würde ich altem Material zu diesem Thema nicht vertrauen.

Das Ganze ist ziemlich kompliziert, weil es von der Selektivität Ihrer Indizes abhängt und ob Sie nach Gleichheit, Ungleichheit und/oder Sortierung fragen, also explain() ist dein einziger Freund, aber hier sind einige Dinge, die ich gefunden habe:

Vorbehalt :Was jetzt kommt, ist eine Mischung aus Versuchsergebnissen, Überlegungen und Vermutungen. Ich könnte Kyles Analogie zu weit ausdehnen und ich könnte sogar völlig falsch liegen (und Pech, denn meine Testergebnisse stimmen nicht mit meiner Argumentation überein).

Es ist klar, dass der Index von A verwendet werden kann, was je nach Selektivität von A sicherlich sehr hilfreich ist. „Überspringen“ von B kann knifflig sein oder auch nicht. Lassen Sie uns das ähnlich wie in Kyles Kochbuchbeispiel halten:

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

Wenn Sie mich jetzt bitten, ein französisches Gericht namens "Chateaubriand" zu finden, kann ich den Index A verwenden und da ich die Zutat nicht kenne, muss ich alle Gerichte in A scannen . Andererseits weiß ich, dass die Liste der Gerichte in jeder Kategorie nach dem Index C sortiert ist , also muss ich in jeder Zutatenliste nur nach den Zeichenfolgen suchen, die beispielsweise mit "Cha" beginnen. Wenn es 50 Zutaten gibt, brauche ich 50 Suchen statt nur einer, aber das ist viel besser, als jedes französische Gericht scannen zu müssen!

In meinen Experimenten war die Anzahl viel kleiner als die Anzahl unterschiedlicher Werte in b :es schien nie 2 zu überschreiten. Ich habe dies jedoch nur mit einer einzigen Sammlung getestet, und es hat wahrscheinlich mit der Selektivität des b zu tun -index.

Wenn Sie mich gebeten haben, Ihnen eine alphabetisch sortierte Liste aller französischen Gerichte zu geben , aber ich würde in Ärger geraten . Nun der Index auf C wertlos ist, müsste ich all diese Indexlisten zusammenführen und sortieren. Dazu muss ich jedes Element scannen.

Dies spiegelt sich in meinen Tests wieder. Hier sind einige vereinfachte Ergebnisse. Die ursprüngliche Sammlung hat Datetimes, Ints und Strings, aber ich wollte die Dinge einfach halten, also sind es jetzt nur Ints.

Im Wesentlichen gibt es nur zwei Klassen von Abfragen:diejenigen, bei denen nscanned <=2 * limit , und diejenigen, die die gesamte Sammlung (120.000 Dokumente) scannen müssen. Der Index ist {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 }});

Ihr Kilometerstand variiert.