Opmerking: Dit antwoord is gebaseerd op MongoDB 3.2.4.
Het is de moeite waard om het gebruik van explain()
te ontdekken
in MongoDB. De explain()
uitvoer van een zoekopdracht (bijv. db.collection.explain().find(...)
) stelt u in staat om te controleren welke index wordt gebruikt in een zoekopdracht en met behulp van db.collection.explain('executionStats')
zal u ook laten zien of de zoekopdracht slaagt of mislukt vanwege SORT
in het geheugen beperking.
$in
Een $in
query kan worden gezien als een reeks gelijkheidsquery's. Bijvoorbeeld {a: {$in: [1,3,5]}}
kan worden gezien als {a:1}, {a:3}, {a:5}
. MongoDB sorteert de $in
array voordat u doorgaat met de query, zodat {$in: [3,5,1]}
is niet anders dan {$in: [1,3,5]}
.
Laten we aannemen dat de collectie een index heeft van
{a:1, b:1}
-
Sorteren op
a
db.coll.find({a: {$in: [1,3,5]}}).sort({a:1})
MongoDB kan de
{a:1,b:1}
. gebruiken index, aangezien deze zoekopdracht kan worden gezien als een samenvoeging van{a:1}, {a:3}, {a:5}
vragen. Sorteren op{a:1}
staat het gebruik toe van indexvoorvoegsel , zodat MongoDB geen sortering in het geheugen hoeft uit te voeren.Dezelfde situatie is ook van toepassing op de vraag:
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({a:1})
sinds
sort({a:1})
gebruikt ook het indexvoorvoegsel (a
in dit geval), een in-memorySORT
podium is daarom niet vereist. -
Sorteren op
b
Dit is een interessanter geval vergeleken met sorteren op
a
. Bijvoorbeeld:db.coll.find({a: {$in: [1,3,5]}}).sort({b:1})
De
explain()
uitvoer van deze query heeft een fase genaamdSORT_MERGE
. Onthoud dat defind()
gedeelte van de zoekopdracht kan worden gezien als{a:1}, {a:3}, {a:5}
.De zoekopdracht
db.coll.find({a:1}).sort({b:1})
hoeft geenSORT
in het geheugen te hebben stadium vanwege de aard van de{a:1,b:1}
index:dat wil zeggen, MongoDB kan eenvoudig door de (gesorteerde) index lopen en documenten gesorteerd opb
retourneren na het voldoen aan de gelijkheidsparameter opa
. Bijvoorbeeld voor elkea
, er zijn veelb
die al zijn gesorteerd opb
vanwege de index.$in
gebruiken , kan de algemene vraag worden gezien als:db.coll.find({a:1}).sort({b:1})
db.coll.find({a:3}).sort({b:1})
db.coll.find({a:5}).sort({b:1})
- Neem de individuele zoekresultaten hierboven en voer een samenvoeging uit met de waarde
b
. De zoekopdracht heeft geen sorteerfase in het geheugen nodig omdat de individuele zoekopdrachtresultaten al zijn gesorteerd opb
. MongoDB hoeft alleen de (reeds gesorteerde) subqueryresultaten samen te voegen tot een enkel resultaat.
Evenzo is de vraag
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({b:1})
gebruikt ook een
SORT_MERGE
en lijkt erg op de bovenstaande query. Het verschil is dat de afzonderlijke query's documenten uitvoeren op basis van een bereik vanb
(in plaats van elkeb
) voor elkea
(die wordt gesorteerd opb
vanwege de index{a:1,b:1}
). Daarom heeft de query geen sorteerfase in het geheugen nodig.
$of
Voor een $or
query om een index te gebruiken, elke clausule in de $or
expressie moet een bijbehorende index hebben
. Als aan deze vereiste is voldaan, kan de query een SORT_MERGE
. gebruiken podium net als een $in
vraag. Bijvoorbeeld:
db.coll.explain().find({$or:[{a:1},{a:3},{a:5}]}).sort({b:1})
heeft een bijna identiek zoekplan, indexgebruik en SORT_MERGE
fase zoals in de $in
voorbeeld hierboven. In wezen kan de vraag worden gezien als:
db.coll.find({a:1}).sort({b:1})
db.coll.find({a:3}).sort({b:1})
db.coll.find({a:5}).sort({b:1})
- Neem de individuele zoekresultaten hierboven en voer een samenvoeging uit met de waarde
b
.
net als de $in
voorbeeld eerder.
Echter, deze vraag:
db.coll.explain().find({$or:[{a:1},{b:1}]}).sort({b:1})
kan geen enkele index gebruiken (aangezien we de {b:1}
. niet hebben inhoudsopgave). Deze zoekopdracht zal resulteren in een collectiescan en bijgevolg heeft een sorteerfase in het geheugen omdat er geen index wordt gebruikt.
Als we echter de index {b:1}
. maken , zal de zoekopdracht als volgt verlopen:
db.coll.find({a:1}).sort({b:1})
db.coll.find({b:1}).sort({b:1})
- Neem de individuele zoekresultaten hierboven en voer een samenvoeging uit met de waarde
b
(die al is gesorteerd op beide subquery's, vanwege de indexen{a:1,b:1}
en{b:1}
).
en MongoDB zal de resultaten van {a:1}
. combineren en {b:1}
query's en voer een samenvoeging uit op de resultaten. Het samenvoegingsproces is lineaire tijd, b.v. O(n)
.
Tot slot, in een $or
query, moet elke term een index hebben, inclusief de sort()
fase. Anders zal MongoDB een sortering in het geheugen moeten uitvoeren.