Poznámka: Tato odpověď je založena na MongoDB 3.2.4.
Stojí za to objevit použití explain()
v MongoDB. explain()
výstup dotazu (např. db.collection.explain().find(...) ) umožňuje zkontrolovat, který index je použit v dotazu, a pomocí db.collection.explain('executionStats')
také vám ukáže, zda byl dotaz úspěšný nebo selhal kvůli SORT v paměti omezení.
$in
$in dotaz lze považovat za sérii dotazů na rovnost. Například {a: {$in: [1,3,5]}} lze si představit jako {a:1}, {a:3}, {a:5} . MongoDB seřadí $in pole před pokračováním v dotazu, takže {$in: [3,5,1]} se neliší od {$in: [1,3,5]} .
Předpokládejme, že kolekce má index
{a:1, b:1}
-
Řazení podle
adb.coll.find({a: {$in: [1,3,5]}}).sort({a:1})MongoDB bude moci používat
{a:1,b:1}index, protože tento dotaz lze považovat za spojení{a:1}, {a:3}, {a:5}dotazy. Řazení podle{a:1}umožňuje použití předpony indexu , takže MongoDB nemusí provádět řazení v paměti.Stejná situace platí také pro dotaz:
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({a:1})od
sort({a:1})také používá předponu indexu (av tomto případě)SORTv paměti fáze proto není vyžadována. -
Řazení podle
bToto je zajímavější případ ve srovnání s řazením podle
a. Například:db.coll.find({a: {$in: [1,3,5]}}).sort({b:1})explain()výstup tohoto dotazu bude mít fázi nazvanouSORT_MERGE. Pamatujte, žefind()část dotazu si lze představit jako{a:1}, {a:3}, {a:5}.Dotaz
db.coll.find({a:1}).sort({b:1})nemusí mít v pamětiSORTfázi kvůli povaze{a:1,b:1}index:to znamená, že MongoDB může jednoduše projít (seřazený) index a vrátit dokumenty seřazené podlebpo splnění parametru rovnosti naa. Např. pro každýa, existuje mnohobkteré jsou již seřazeny podlebkvůli indexu.Pomocí
$in, celkový dotaz lze považovat za:db.coll.find({a:1}).sort({b:1})db.coll.find({a:3}).sort({b:1})db.coll.find({a:5}).sort({b:1})- Vezměte výsledky jednotlivých dotazů výše a proveďte sloučení pomocí hodnoty
b. Dotaz nepotřebuje fázi řazení v paměti protože výsledky jednotlivých dotazů jsou již seřazeny podleb. MongoDB stačí sloučit (již seřazené) výsledky dílčích dotazů do jednoho výsledku.
Podobně dotaz
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({b:1})také používá
SORT_MERGEfázi a je velmi podobný dotazu výše. Rozdíl je v tom, že jednotlivé dotazy vydávají dokumenty na základě rozsahub(místo každýb) pro každýa(které budou seřazeny podlebkvůli indexu{a:1,b:1}). Dotaz tedy nepotřebuje fázi řazení v paměti.
$nebo
Pro $or dotaz na použití indexu, každá klauzule v $or výraz musí mít přidružený index
. Pokud je tento požadavek splněn, je možné, aby dotaz použil SORT_MERGE fázi stejně jako $in dotaz. Například:
db.coll.explain().find({$or:[{a:1},{a:3},{a:5}]}).sort({b:1})
bude mít téměř identický plán dotazů, použití indexu a SORT_MERGE fázi jako v $in příklad výše. Dotaz lze v zásadě považovat za:
db.coll.find({a:1}).sort({b:1})db.coll.find({a:3}).sort({b:1})db.coll.find({a:5}).sort({b:1})- Vezměte výsledky jednotlivých dotazů výše a proveďte sloučení pomocí hodnoty
b.
stejně jako $in příklad výše.
Tento dotaz však:
db.coll.explain().find({$or:[{a:1},{b:1}]}).sort({b:1})
nelze použít žádný index (protože nemáme {b:1} index). Tento dotaz bude mít za následek skenování kolekce a následně bude mít fázi řazení v paměti protože není použit žádný index.
Pokud však vytvoříme index {b:1} , dotaz bude pokračovat takto:
db.coll.find({a:1}).sort({b:1})db.coll.find({b:1}).sort({b:1})- Vezměte výsledky jednotlivých dotazů výše a proveďte sloučení pomocí hodnoty
b(který je již řazen u obou dílčích dotazů, kvůli indexům{a:1,b:1}a{b:1}).
a MongoDB zkombinují výsledky {a:1} a {b:1} dotazy a provést sloučení výsledků. Proces slučování je lineární čas, kupř. O(n) .
Na závěr v $or každý výraz musí mít index, včetně sort() etapa. Jinak bude muset MongoDB provést řazení v paměti.