MongoDB a Big Data

Pokud potřebujete databázi pro velké objemy dat (řádově miliardy a více záznamů) a uvažujete o nasazení MongoDB, pak je tento článek určený právě pro Vás. Níže uvedená fakta reflektují mé zkušenosti s mongo clusterem a pokud se jich budete držet, můžete se vyhnout častým chybám. Prioritou je konzistence dat a jejich dostupnost (viz CAP teorém).

MongoDB 3.2 a novější

Použijte nejnovější verzi monga označovanou jako "stable". Verze 3.2 vyšla nedávno a oproti verzi 3.0 přináší (mimo jiné) zlepšení výkonu a částečné indexy (viz níže).

Používejte WiredTiger

Od verze 3.0 došlo k integrování storage enginu WiredTiger. Ten je jednoznačně nejlepším storage enginem a od verze 3.2 i výchozím. Oproti MMAPv1 umožňuje:

  • zamykání na úrovni dokumentů (skvělý výkon pro souběžný zápis),
  • automatická komprese dat i indexů (úspora místa na disku a tím i I/O operací),
  • journal (zajištěna integrita dat při výpadku).

Mimochodem, journal určitě v produkci používejte (výkon se sníží jen o jednotky procent). Pokud to technické možnosti dovolí, mějte ho vždy na jiném disku, než ostatní soubory databáze.

Souběžnost je základ

MongoDB je skvěle přizpůsobena pro paralelní práci s daty. Import dat v jednom procesu není totéž, jako import dat v deseti procesech zároveň.

Dávková práce s daty

Využívejte dávkového zpracování dokumentů. Aktualizace nebo vkládání dokumentů po jednotkách je řádově pomalejší, než v bulku (optimální počet dokumentů je 1000). Viz dokumentace PyMongo.

Replikujte

Zvyšte spolehlivost svých dat replikací. Dbejte na to, aby replikační set tvořily alespoň 3 členové (1 primární, 2 sekundární). Pokud máte stroje s různým výkonem, nastavte priority členům podle jejich výkonu. 

Shardujte

Když velká data, tak v clusteru. Věnujte velkou pozornost volbě shardovacího klíče. Pokud se na váš dokument nejčastěji doptáváte přes nějakou hodnotu, pak shardujte podle ní. Mongos (query balancer) pak zbytečně neposílá dotaz všem shardům, ale jen těm, které dokument(y) obsahují.

Vyvarujte se shardování podle vzestupného/sestupného indexu (zejména u řetězců). Nepoužívejte:

sh.shardCollection('kolekce', {field: 1})

raději takto:

sh.shardCollection('kolekce', {field: 'hashed'})

MongoDB pak mnohem rychleji zvládá rozdělování chunků (split vector) i jejich balancování (vyrovnávání počtu chunků mezi jednotlivými shardy).

Index v operační paměti

Index kolekcí by se měl vejít do operační paměti. Pokud se tak nestane, budete zaznamenávat ztrátu výkonu díky iowait při jeho načítání z disku. Velikost indexu (v bajtech) můžete zjistit pomocí příkazu:

db.kolekce.totalIndexSize()

Pokud operační paměť jednoduše nemáte, můžete zkusit následující finty:

  • umístit soubory s indexy na zvláštní disk (nejlépe SSD),
  • dotazovat se na data (čtení, update) podle vzestupného/sestupného indexu (větší pravděpodobnost blízkosti dat) namísto hashe (rovnoměrně rozprostření přes celý index),
  • snížit WiredTiger cache size (uchovává nekomprimovaná data) a tím dát větší prostor cache filesystému operačního systému (má smysl jen v případě, že máte zapnutou kompresi dat), protože bloky na disku jsou komprimované.

Částečné indexy

Novinkou od verze 3.2 jsou částečné indexy. Díky ním ušetříte místo na disku a hlavně I/O operace potřebné pro údržbu indexu. Vždy indexujte pouze to, co potřebujete, nic víc.

Stejná velikost aktualizovaného dokumentu

Je mnohem rychlejší provést update dokumentu, kde je výsledná velikost stejná nebo menší. Pokud bude velikost dokumentu větší, mongo musí provést realokaci a aktualizaci souvisejících indexů. 

Raději insert než update

Vložení dat bude vždy mnohem rychlejší, než jejich aktualizace. Pokud tedy nepotřebujete nutně agregovat za běhu, je lepší ukládat všechna data jako nové dokumenty.