Hinweis: Diese Antwort basiert auf MongoDB 3.2.4.
Es lohnt sich, die Verwendung von explain() zu entdecken
in MongoDB. Der explain()
Ausgabe einer Abfrage (z. B. db.collection.explain().find(...)). ) können Sie überprüfen, welcher Index in einer Abfrage verwendet wird, und mit db.collection.explain('executionStats')
zeigt Ihnen auch, ob die Abfrage aufgrund von SORT im Speicher erfolgreich ist oder fehlschlägt Einschränkung.
$in
Ein $in Die Abfrage kann als eine Reihe von Gleichheitsabfragen betrachtet werden. Beispiel:{a: {$in: [1,3,5]}} könnte man sich vorstellen als {a:1}, {a:3}, {a:5} . MongoDB sortiert den $in Array, bevor Sie mit der Abfrage fortfahren, sodass {$in: [3,5,1]} unterscheidet sich nicht von {$in: [1,3,5]} .
Nehmen wir an, die Sammlung hat einen Index von
{a:1, b:1}
-
Sortierung nach
adb.coll.find({a: {$in: [1,3,5]}}).sort({a:1})MongoDB kann den
{a:1,b:1}verwenden index, da diese Abfrage als Vereinigung von{a:1}, {a:3}, {a:5}betrachtet werden kann Abfragen. Sortieren nach{a:1}erlaubt die Verwendung von Indexpräfix , sodass MongoDB keine In-Memory-Sortierung durchführen muss.Die gleiche Situation gilt auch für die Abfrage:
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({a:1})seit
sort({a:1})verwendet auch das Indexpräfix (ain diesem Fall), ein speicherresidentesSORTStufe ist daher nicht erforderlich. -
Sortierung nach
bDies ist ein interessanterer Fall im Vergleich zum Sortieren nach
a. Zum Beispiel:db.coll.find({a: {$in: [1,3,5]}}).sort({b:1})Das
explain()Die Ausgabe dieser Abfrage hat eine Phase namensSORT_MERGE. Denken Sie daran, dassfind()Teil der Abfrage kann man sich als{a:1}, {a:3}, {a:5}vorstellen .Die Abfrage
db.coll.find({a:1}).sort({b:1})muss keinSORTim Speicher haben Phase aufgrund der Natur des{a:1,b:1}index:Das heißt, MongoDB kann einfach den (sortierten) Index durchlaufen und Dokumente sortiert nachbzurückgeben nachdem der Gleichheitsparameter aufaerfüllt wurde . Z. B. für jedena, gibt es vielebdie bereits nachbsortiert sind aufgrund des Indexes.Verwenden von
$in, kann man sich die Gesamtabfrage wie folgt vorstellen:db.coll.find({a:1}).sort({b:1})db.coll.find({a:3}).sort({b:1})db.coll.find({a:5}).sort({b:1})- Nehmen Sie die einzelnen Abfrageergebnisse oben und führen Sie eine Zusammenführung mit dem Wert von
bdurch . Die Abfrage benötigt keine In-Memory-Sortierungsphase da die einzelnen Abfrageergebnisse bereits nachbsortiert sind . MongoDB muss nur die (bereits sortierten) Unterabfrageergebnisse zu einem einzigen Ergebnis zusammenführen.
Ebenso die Abfrage
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({b:1})verwendet auch ein
SORT_MERGEStufe und ist der obigen Abfrage sehr ähnlich. Der Unterschied besteht darin, dass die einzelnen Abfragen Dokumente basierend auf einer Reihe von ausgebenb(statt alleb) für jedena(die nachbsortiert werden aufgrund des Index{a:1,b:1}). Daher benötigt die Abfrage keine In-Memory-Sortierungsphase.
$oder
Für ein $or Abfrage, um einen Index zu verwenden, jede Klausel im $or Ausdruck muss ein Index zugeordnet sein
. Wenn diese Anforderung erfüllt ist, kann die Abfrage einen SORT_MERGE verwenden Bühne genau wie ein $in Anfrage. Zum Beispiel:
db.coll.explain().find({$or:[{a:1},{a:3},{a:5}]}).sort({b:1})
wird einen fast identischen Abfrageplan, Indexgebrauch und SORT_MERGE haben Stufe wie in $in Beispiel oben. Im Wesentlichen kann man sich die Abfrage wie folgt vorstellen:
db.coll.find({a:1}).sort({b:1})db.coll.find({a:3}).sort({b:1})db.coll.find({a:5}).sort({b:1})- Nehmen Sie die einzelnen Abfrageergebnisse oben und führen Sie eine Zusammenführung mit dem Wert von
bdurch .
genau wie $in Beispiel vor.
Diese Abfrage jedoch:
db.coll.explain().find({$or:[{a:1},{b:1}]}).sort({b:1})
kann keinen Index verwenden (da wir den {b:1} nicht haben Index). Diese Abfrage führt zu einem Sammlungsscan und hat folglich eine In-Memory-Sortierungsphase da kein Index verwendet wird.
Wenn wir jedoch den Index {b:1} erstellen , wird die Abfrage wie folgt fortgesetzt:
db.coll.find({a:1}).sort({b:1})db.coll.find({b:1}).sort({b:1})- Nehmen Sie die einzelnen Abfrageergebnisse oben und führen Sie eine Zusammenführung mit dem Wert von
bdurch (die bei beiden Unterabfragen bereits sortiert ist, aufgrund der Indizes{a:1,b:1}und{b:1}).
und MongoDB kombiniert die Ergebnisse von {a:1} und {b:1} Abfragen und führen Sie eine Zusammenführung der Ergebnisse durch. Der Zusammenführungsprozess ist eine lineare Zeit, z. O(n) .
Abschließend in einem $or Abfrage muss jeder Begriff einen Index haben, einschließlich sort() Bühne. Andernfalls muss MongoDB eine In-Memory-Sortierung durchführen.