Obs! Det här svaret är baserat på MongoDB 3.2.4.
Det är värt att upptäcka användningen av explain()
i MongoDB. explain()
utdata från en fråga (t.ex. db.collection.explain().find(...) ) låter dig kontrollera vilket index som används i en fråga och använda db.collection.explain('executionStats')
kommer också att visa dig om frågan lyckas eller misslyckas på grund av SORT i minnet begränsning.
$in
En $in fråga kan ses som en serie jämställdhetsfrågor. Till exempel {a: {$in: [1,3,5]}} kan ses som {a:1}, {a:3}, {a:5} . MongoDB kommer att sortera $in array innan du fortsätter med frågan, så att {$in: [3,5,1]} är inte annorlunda än {$in: [1,3,5]} .
Låt oss anta att samlingen har ett index på
{a:1, b:1}
-
Sorterar efter
adb.coll.find({a: {$in: [1,3,5]}}).sort({a:1})MongoDB kommer att kunna använda
{a:1,b:1}index, eftersom den här frågan kan ses som en förening av{a:1}, {a:3}, {a:5}frågor. Sorterar efter{a:1}tillåter användning av indexprefix , så MongoDB behöver inte utföra en sortering i minnet.Samma situation gäller även för frågan:
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({a:1})sedan
sort({a:1})använder också indexprefixet (ai detta fall), enSORTi minnet steg krävs därför inte. -
Sorterar efter
bDetta är ett mer intressant fall jämfört med att sortera efter
a. Till exempel:db.coll.find({a: {$in: [1,3,5]}}).sort({b:1})explain()utdata från denna fråga kommer att ha ett steg som heterSORT_MERGE. Kom ihåg attfind()del av frågan kan ses som{a:1}, {a:3}, {a:5}.Frågan
db.coll.find({a:1}).sort({b:1})behöver inte ha enSORTi minnet steg på grund av{a:1,b:1}karaktär index:det vill säga MongoDB kan helt enkelt gå igenom det (sorterade) indexet och returnera dokument sorterade efterbefter att ha uppfyllt likhetsparametern påa. Till exempel för varjea, det finns mångabsom redan är sorterade efterbpå grund av indexet.Använder
$in, kan den övergripande frågan ses som:db.coll.find({a:1}).sort({b:1})db.coll.find({a:3}).sort({b:1})db.coll.find({a:5}).sort({b:1})- Ta de enskilda frågeresultaten ovan och utför en sammanslagning med värdet
b. Frågan behöver inte ett sorteringssteg i minnet eftersom de individuella frågeresultaten redan är sorterade efterb. MongoDB behöver bara slå samman de (redan sorterade) sub-frågeresultaten till ett enda resultat.
På samma sätt är frågan
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({b:1})använder också en
SORT_MERGEsteg och är mycket lik frågan ovan. Skillnaden är att de enskilda frågorna matar ut dokument baserat på ett antalb(istället för varjeb) för varjea(som kommer att sorteras efterbpå grund av indexet{a:1,b:1}). Därför behöver frågan inte ett sorteringssteg i minnet.
$or
För en $or fråga om att använda ett index, varje klausul i $or uttryck måste ha ett index kopplat till sig
. Om detta krav är uppfyllt är det möjligt för frågan att använda en SORT_MERGE steg precis som en $in fråga. Till exempel:
db.coll.explain().find({$or:[{a:1},{a:3},{a:5}]}).sort({b:1})
kommer att ha en nästan identisk frågeplan, indexanvändning och SORT_MERGE steg som i $in exemplet ovan. I huvudsak kan frågan ses som:
db.coll.find({a:1}).sort({b:1})db.coll.find({a:3}).sort({b:1})db.coll.find({a:5}).sort({b:1})- Ta de enskilda frågeresultaten ovan och utför en sammanslagning med värdet
b.
precis som $in exempel tidigare.
Men den här frågan:
db.coll.explain().find({$or:[{a:1},{b:1}]}).sort({b:1})
kan inte använda något index (eftersom vi inte har {b:1} index). Den här frågan kommer att resultera i en samlingsskanning och kommer därför att ha ett sorteringssteg i minnet eftersom inget index används.
Om vi däremot skapar indexet {b:1} , kommer frågan att fortsätta så här:
db.coll.find({a:1}).sort({b:1})db.coll.find({b:1}).sort({b:1})- Ta de enskilda frågeresultaten ovan och utför en sammanslagning med värdet
b(vilket redan är sorterat vid båda underfrågorna, på grund av indexen{a:1,b:1}och{b:1}).
och MongoDB kommer att kombinera resultaten av {a:1} och {b:1} frågor och utför en sammanslagning av resultaten. Sammanslagningsprocessen är linjär tid, t.ex. O(n) .
Sammanfattningsvis i en $or fråga måste varje term ha ett index, inklusive sort() skede. Annars måste MongoDB utföra en sortering i minnet.