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
a
db.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 (a
i dette tilfælde), enSORT
i hukommelsen trin er derfor ikke påkrævet. -
Sortering efter
b
Dette 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 enSORT
i 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 efterb
efter at have opfyldt lighedsparameteren påa
. F.eks. for hvera
, der er mangeb
som allerede er sorteret efterb
på 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_MERGE
fase 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 efterb
på 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.