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
a
db.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 (a
in diesem Fall), ein speicherresidentesSORT
Stufe ist daher nicht erforderlich. -
Sortierung nach
b
Dies 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 keinSORT
im 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 nachb
zurückgeben nachdem der Gleichheitsparameter aufa
erfüllt wurde . Z. B. für jedena
, gibt es vieleb
die bereits nachb
sortiert 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
b
durch . Die Abfrage benötigt keine In-Memory-Sortierungsphase da die einzelnen Abfrageergebnisse bereits nachb
sortiert 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_MERGE
Stufe 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 nachb
sortiert 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
b
durch .
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
b
durch (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.