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
adb.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 (ain dit geval), een in-memorySORTpodium is daarom niet vereist. -
Sorteren op
bDit 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 geenSORTin 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 opbretourneren na het voldoen aan de gelijkheidsparameter opa. Bijvoorbeeld voor elkea, er zijn veelbdie al zijn gesorteerd opbvanwege de index.$ingebruiken , 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_MERGEen 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 opbvanwege 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.