Bemærk: Dette svar er baseret på MongoDB 3.2.4.
Det er umagen værd at opdage brugen af explain()
i MongoDB. explain()
output af en forespørgsel (f.eks. db.collection.explain().find(...) ) giver dig mulighed for at kontrollere, hvilket indeks der bruges i en forespørgsel, og bruge db.collection.explain('executionStats')
vil også vise dig, om forespørgslen lykkes eller mislykkes på grund af SORT i hukommelsen begrænsning.
$in
En $in forespørgsel kan opfattes som en serie af ligestillingsforespørgsler. For eksempel {a: {$in: [1,3,5]}} kunne opfattes som {a:1}, {a:3}, {a:5} . MongoDB vil sortere $in array, før du fortsætter med forespørgslen, så {$in: [3,5,1]} er ikke anderledes end {$in: [1,3,5]} .
Lad os antage, at samlingen har et indeks på
{a:1, b:1}
-
Sortering efter
adb.coll.find({a: {$in: [1,3,5]}}).sort({a:1})MongoDB vil være i stand til at bruge
{a:1,b:1}indeks, da denne forespørgsel kan opfattes som en forening af{a:1}, {a:3}, {a:5}forespørgsler. Sortering efter{a:1}tillader brug af indekspræfiks , så MongoDB behøver ikke at udføre en sortering i hukommelsen.Den samme situation gælder også for forespørgslen:
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({a:1})siden
sort({a:1})bruger også indekspræfikset (ai dette tilfælde), enSORTi hukommelsen trin er derfor ikke påkrævet. -
Sortering efter
bDette er et mere interessant tilfælde sammenlignet med sortering efter
a. For eksempel:db.coll.find({a: {$in: [1,3,5]}}).sort({b:1})explain()output af denne forespørgsel vil have et trin kaldetSORT_MERGE. Husk atfind()del af forespørgslen kan opfattes som{a:1}, {a:3}, {a:5}.Forespørgslen
db.coll.find({a:1}).sort({b:1})behøver ikke at have enSORTi hukommelsen trin på grund af arten af {a:1,b:1}indeks:det vil sige, MongoDB kan simpelthen gå gennem (sorteret) indeks og returnere dokumenter sorteret efterbefter at have opfyldt lighedsparameteren påa. F.eks. for hvera, der er mangebsom allerede er sorteret efterbpå grund af indekset.Bruger
$in, kan den overordnede forespørgsel opfattes 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})- Tag de individuelle forespørgselsresultater ovenfor, og udfør en fletning med værdien
b. Forespørgslen behøver ikke et sorteringstrin i hukommelsen fordi de individuelle forespørgselsresultater allerede er sorteret efterb. MongoDB skal bare flette de (allerede sorterede) underforespørgselsresultater til et enkelt resultat.
På samme måde er forespørgslen
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({b:1})bruger også en
SORT_MERGEfase og ligner meget forespørgslen ovenfor. Forskellen er, at de enkelte forespørgsler udskriver dokumenter baseret på en række afb(i stedet for hverb) for hvera(som vil blive sorteret efterbpå grund af indekset{a:1,b:1}). Derfor behøver forespørgslen ikke et sorteringstrin i hukommelsen.
$or
For en $or forespørgsel om at bruge et indeks, hver klausul i $or udtryk skal have et indeks tilknyttet
. Hvis dette krav er opfyldt, er det muligt for forespørgslen at anvende en SORT_MERGE trin ligesom en $in forespørgsel. For eksempel:
db.coll.explain().find({$or:[{a:1},{a:3},{a:5}]}).sort({b:1})
vil have en næsten identisk forespørgselsplan, indeksbrug og SORT_MERGE trin som i $in eksemplet ovenfor. Grundlæggende kan forespørgslen opfattes 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})- Tag de individuelle forespørgselsresultater ovenfor, og udfør en fletning med værdien
b.
ligesom $in eksempel før.
Men denne forespørgsel:
db.coll.explain().find({$or:[{a:1},{b:1}]}).sort({b:1})
kan ikke bruge noget indeks (da vi ikke har {b:1} indeks). Denne forespørgsel vil resultere i en samlingsscanning og vil have et sorteringstrin i hukommelsen da der ikke bruges noget indeks.
Hvis vi derimod opretter indekset {b:1} , vil forespørgslen fortsætte som:
db.coll.find({a:1}).sort({b:1})db.coll.find({b:1}).sort({b:1})- Tag de individuelle forespørgselsresultater ovenfor, og udfør en fletning med værdien
b(som allerede er sorteret ved begge underforespørgsler på grund af indekserne{a:1,b:1}og{b:1}).
og MongoDB vil kombinere resultaterne af {a:1} og {b:1} forespørgsler og udføre en fletning af resultaterne. Sammenlægningsprocessen er lineær tid, f.eks. O(n) .
Afslutningsvis i en $or forespørgsel, skal hvert udtryk have et indeks, inklusive sort() scene. Ellers bliver MongoDB nødt til at udføre en sortering i hukommelsen.