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í
bvě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 prosort({b:1,c:1})nebosort({b:-1,c:-1})ale nesort({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í
bvě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
-
MongoDB používá pro většinu dotazů pouze jeden index. Chcete-li se například vyhnout v paměti
SORTfázi v dotazudb.a.find({a:1}).sort({b:1})index musí pokrývat obě
aabpole 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.
-
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ásledujesort()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:
- MinKey (interní typ)
- Nulé
- Čísla (ints, longs, double, desetinná místa)
- Symbol, řetězec
- Objekt
- Pole
- BinData
- ObjectId
- Booleovská hodnota
- Datum
- Časové razítko
- Regulární výraz
- 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.