Uwaga: Ta odpowiedź jest oparta na MongoDB 3.2.4.
Warto odkryć zastosowanie explain()
w MongoDB. explain()
dane wyjściowe zapytania (np. db.collection.explain().find(...) ) umożliwia sprawdzenie, który indeks jest używany w zapytaniu, i użycie db.collection.explain('executionStats')
pokaże również, czy zapytanie się powiedzie, czy nie, z powodu znajdującego się w pamięci SORT ograniczenia.
$w
$in zapytanie można traktować jako serię zapytań o równość. Na przykład {a: {$in: [1,3,5]}} można uznać za {a:1}, {a:3}, {a:5} . MongoDB posortuje $in tablicę przed kontynuowaniem zapytania, aby {$in: [3,5,1]} nie różni się od {$in: [1,3,5]} .
Załóżmy, że kolekcja ma indeks
{a:1, b:1}
-
Sortowanie według
adb.coll.find({a: {$in: [1,3,5]}}).sort({a:1})MongoDB będzie mógł korzystać z
{a:1,b:1}indeks, ponieważ to zapytanie może być traktowane jako połączenie{a:1}, {a:3}, {a:5}zapytania. Sortowanie według{a:1}umożliwia użycie prefiksu indeksu , więc MongoDB nie musi wykonywać sortowania w pamięci.Ta sama sytuacja dotyczy również zapytania:
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({a:1})od
sort({a:1})używa również prefiksu indeksu (aw tym przypadku), w pamięciSORTetap nie jest zatem wymagany. -
Sortowanie według
bJest to ciekawszy przypadek w porównaniu z sortowaniem według
a. Na przykład:db.coll.find({a: {$in: [1,3,5]}}).sort({b:1})explain()wyjście tego zapytania będzie miało etap o nazwieSORT_MERGE. Pamiętaj, żefind()część zapytania można traktować jako{a:1}, {a:3}, {a:5}.Zapytanie
db.coll.find({a:1}).sort({b:1})nie musi mieć w pamięciSORTetap ze względu na charakter{a:1,b:1}index:to znaczy, MongoDB może po prostu przejrzeć (posortowany) indeks i zwrócić dokumenty posortowane wedługbpo spełnieniu parametru równości naa. Np. dla każdegoa, istnieje wielebktóre są już posortowane wedługbze względu na indeks.Korzystanie z
$in, ogólne zapytanie można traktować jako:db.coll.find({a:1}).sort({b:1})db.coll.find({a:3}).sort({b:1})db.coll.find({a:5}).sort({b:1})- Weź powyższe wyniki poszczególnych zapytań i wykonaj scalanie przy użyciu wartości
b. Zapytanie nie wymaga etapu sortowania w pamięci ponieważ wyniki poszczególnych zapytań są już posortowane wedługb. MongoDB wystarczy połączyć (już posortowane) wyniki podzapytania w jeden wynik.
Podobnie zapytanie
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({b:1})używa również
SORT_MERGEetap i jest bardzo podobny do powyższego zapytania. Różnica polega na tym, że poszczególne zapytania do dokumentów wyjściowych są oparte na zakresieb(zamiast cob) dla każdegoa(które zostaną posortowane wedługbze względu na indeks{a:1,b:1}). Dlatego zapytanie nie wymaga etapu sortowania w pamięci.
$lub
Dla $or zapytanie do użycia indeksu, każda klauzula w $or wyrażenie musi mieć powiązany z nim indeks
. Jeśli ten wymóg jest spełniony, zapytanie może użyć SORT_MERGE etap tak jak $in zapytanie. Na przykład:
db.coll.explain().find({$or:[{a:1},{a:3},{a:5}]}).sort({b:1})
będzie miał prawie identyczny plan zapytań, użycie indeksu i SORT_MERGE etap jak w $in przykład powyżej. Zasadniczo zapytanie można traktować jako:
db.coll.find({a:1}).sort({b:1})db.coll.find({a:3}).sort({b:1})db.coll.find({a:5}).sort({b:1})- Weź powyższe wyniki poszczególnych zapytań i wykonaj scalanie przy użyciu wartości
b.
podobnie jak $in przykład wcześniej.
Jednak to zapytanie:
db.coll.explain().find({$or:[{a:1},{b:1}]}).sort({b:1})
nie można używać żadnego indeksu (ponieważ nie mamy {b:1} indeks). To zapytanie spowoduje przeskanowanie kolekcji i w konsekwencji będzie miał etap sortowania w pamięci ponieważ nie jest używany żaden indeks.
Jeśli jednak utworzymy indeks {b:1} , zapytanie będzie przebiegać następująco:
db.coll.find({a:1}).sort({b:1})db.coll.find({b:1}).sort({b:1})- Weź powyższe wyniki poszczególnych zapytań i wykonaj scalanie przy użyciu wartości
b(który jest już posortowany w obu zapytaniach podrzędnych, ze względu na indeksy{a:1,b:1}i{b:1}).
a MongoDB połączy wyniki {a:1} i {b:1} zapytań i wykonaj scalanie wyników. Proces scalania jest czasem liniowym, m.in. O(n) .
Podsumowując, w $or zapytanie, każdy termin musi mieć indeks, w tym sort() etap. W przeciwnym razie MongoDB będzie musiał wykonać sortowanie w pamięci.