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

Jak funguje řazení pomocí indexu v MongoDB?

Indexy v MongoDB jsou uloženy ve struktuře B-stromu, kde každá položka indexu ukazuje na konkrétní místo na disku. Použití struktury B-stromu také znamená, že index MongoDB je uložen v seřazeném pořadí, vždy se projde v daném pořadí a pro MongoDB je levné načíst sérii dokumentů v seřazeném pořadí prostřednictvím indexů.

Aktualizovat :Struktura B-stromu platí pro úložiště MMAPv1, ale je implementována mírně odlišně pomocí úložiště WiredTiger (výchozí od MongoDB 3.2). Základní myšlenka zůstává stejná, kdy je levné procházet index v seřazeném pořadí.

A SORT fáze (tj. řazení v paměti) v dotazu je omezena na 32 MB využití paměti. Dotaz se nezdaří, pokud SORT etapa tuto hranici překračuje. Tento limit lze obejít využitím setříděné povahy indexů, takže MongoDB může vrátit dotaz s sort() parametr bez provedení řazení v paměti.

Předpokládejme, že dotaz má tvar:

    db.a.find({b:{$gt:100}, c:{$gt:200}}).sort(...)

s kolekcí a s indexem:

    db.a.createIndex({b:1,c:1})

Existují dva možné scénáře, kdy sort() fáze je uvedena v dotazu:

1. MongoDB nemůže použít seřazenou povahu indexu a musí provést v paměti SORT etapa .

Toto je výsledek, pokud dotaz nemůže použít "prefix indexu". Například:

    db.a.find({b:{$gt:100}, c:{$gt:200}}).sort({c:1})

V dotazu výše index {b:1,c:1} lze použít k:

  • Přiřaďte dokumenty obsahující b větší než 100 pro {b:{$gt:100}} část dotazu.
  • Nicméně není zaručeno, že vrácené dokumenty jsou seřazeny podle c .

Proto MongoDB nemá jinou možnost, než provést řazení v paměti. explain() výstup tohoto dotazu bude mít SORT etapa. Toto SORT etapa by byla omezena na 32 MB využití paměti.

2. MongoDB může využívat tříděný charakter indexu .

Toto je výsledek, pokud dotaz používá:

  • Klíče řazení, které odpovídá pořadí indexu, a
  • Určuje stejné pořadí jako index (tj. index {b:1,c:1} lze použít pro sort({b:1,c:1}) nebo sort({b:-1,c:-1}) ale ne sort({b:1,c:-1}) )

Například:

    db.a.find({b:{$gt:100}, c:{$gt:200}}).sort({b:1})

V dotazu výše index {b:1,c:1} lze použít k:

  • Přiřaďte dokumenty obsahující b větší než 100 pro {b:{$gt:100}} část dotazu.
  • V tomto případě MongoDB může zaručit, že vrácené dokumenty jsou seřazeny podle b .

explain() výstup výše uvedeného dotazu nebude mít SORT etapa. Také funkce explain() výstup dotazu s a bez sort() jsou identické . V podstatě dostáváme sort() zdarma.

Cenným zdrojem pro pochopení tohoto tématu je Optimalizace složených indexů MongoDB. Vezměte prosím na vědomí, že tento blogový příspěvek byl napsán již v roce 2012. Ačkoli některá terminologie může být zastaralá, technická stránka příspěvku je stále relevantní.

Aktualizace doplňujících otázek

  1. MongoDB používá pro většinu dotazů pouze jeden index. Chcete-li se například vyhnout v paměti SORT fázi v dotazu

    db.a.find({a:1}).sort({b:1})
    

    index musí pokrývat obě a a b pole současně; např. složený index, například {a:1,b:1} je požadováno. Nemůžete mít dva samostatné indexy {a:1} a {b:1} a očekávejte {a:1} index, který se má použít pro část rovnosti, a {b:1} index, který se má použít pro třídicí část. V tomto případě si MongoDB vybere jeden ze dvou indexů.

    Proto je správné, že jsou výsledky seřazeny, protože jsou vyhledány a vráceny v pořadí podle indexu.

  2. Chcete-li se vyhnout řazení v paměti pomocí složeného indexu, první část indexu musí odpovídat části rovnosti dotazu a druhá část musí odpovídat třídění dotazu (jak je uvedeno ve vysvětlení pro (1) výše).

    Pokud máte dotaz jako je tento:

    db.a.find({}).sort({a:1})
    

    index {a:1,b:1} lze použít pro třídící část (protože v podstatě vracíte celou kolekci). A pokud váš dotaz vypadá takto:

    db.a.find({a:1}).sort({b:1})
    

    stejný index {a:1,b:1} lze také použít pro obě části dotazu. Také:

    db.a.find({a:1,b:1})
    

    může také použít stejný index {a:1,b:1}

    Všimněte si vzoru zde:find() následuje sort() parametry sledují pořadí indexu {a:1,b:1} . Složený index proto musí být uspořádán podle rovnosti -> řazení .

Aktualizace týkající se řazení různých typů

Pokud má pole mezi dokumenty různé typy (např. pokud a je řetězec v jednom dokumentu, číslo v ostatních, booleovský v dalším), jak probíhá řazení?

Odpověď je pořadí porovnání typu MongoDB BSON. Abychom parafrázovali manuálovou stránku, pořadí je:

  1. MinKey (interní typ)
  2. Nulé
  3. Čísla (ints, longs, double, desetinná místa)
  4. Symbol, řetězec
  5. Objekt
  6. Pole
  7. BinData
  8. ObjectId
  9. Booleovská hodnota
  10. Datum
  11. Časové razítko
  12. Regulární výraz
  13. MaxKey (interní typ)

Takže z výše uvedeného příkladu s použitím vzestupného pořadí se nejprve zobrazí dokumenty obsahující čísla, poté řetězce a poté boolean.




  1. redis vs hazelcast

  2. 5 způsobů, jak vybrat řádky s minimální hodnotou pro jejich skupinu v SQL

  3. Počítání v úložišti Spring Data MongoDB

  4. Pracovník fronty Redis se zhroutí v utcparse