sql >> Databáze >  >> NoSQL >> MongoDB

Jak funguje řazení s dotazy `$or` a `$in` v MongoDB?

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 a

      db.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 (a v tomto případě) SORT v paměti fáze proto není vyžadována.

  • Řazení podle b

    Toto 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 nazvanou SORT_MERGE . Pamatujte, že find() čá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ěti SORT fá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é podle b po splnění parametru rovnosti na a . Např. pro každý a , existuje mnoho b které jsou již seřazeny podle b kvů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 podle b . 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_MERGE fázi a je velmi podobný dotazu výše. Rozdíl je v tom, že jednotlivé dotazy vydávají dokumenty na základě rozsahu b (místo každý b ) pro každý a (které budou seřazeny podle b kvů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.




  1. Proč ovladač mongoDB Node vytváří nechtěná připojení?

  2. MongoDB – Získejte nejnovější nenulovou hodnotu pole z dokumentů s časovým razítkem

  3. Vytiskněte hodnotu dokumentu v prostředí mongodb

  4. Pochopení odolnosti a bezpečnosti zápisu v MongoDB