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

Jak optimalizovat výkon MongoDB

Vynikající výkon databáze je důležitý při vývoji aplikací s MongoDB. Někdy se může celkový proces poskytování dat zhoršit z mnoha důvodů, z nichž některé zahrnují:

  • Nevhodné vzory návrhu schématu
  • Nesprávné použití nebo žádné použití strategií indexování
  • Nedostatečný hardware
  • Prodleva replikace
  • Špatně fungující techniky dotazování

Některé z těchto překážek vás mohou donutit zvýšit hardwarové zdroje, zatímco jiné ne. Například špatné struktury dotazů mohou způsobit, že zpracování dotazu bude trvat dlouho, což způsobí zpoždění repliky a možná i určitou ztrátu dat. V tomto případě si člověk může myslet, že možná úložná paměť nestačí a že je pravděpodobně třeba ji zvětšit. Tento článek pojednává o nejvhodnějších postupech, které můžete použít ke zvýšení výkonu vaší databáze MongoDB.

Návrh schématu

V zásadě dva nejčastěji používané vztahy schématu jsou...

  • Jedna k několika
  • Jedna k mnoha

Zatímco nejúčinnějším návrhem schématu je vztah One-to-Many, každý má své výhody a omezení.

Osobně k několika

V tomto případě pro dané pole existují vložené dokumenty, ale nejsou indexovány s identitou objektu.

Zde je jednoduchý příklad:

{
      userName: "Brian Henry",
      Email : "[email protected]",
      grades: [
             {subject: ‘Mathematics’,  grade: ‘A’},
             {subject: English,  grade: ‘B’},
      ]
}

Jednou z výhod použití tohoto vztahu je, že můžete získat vložené dokumenty pomocí jediného dotazu. Z hlediska dotazování však nemáte přístup k jedinému vloženému dokumentu. Pokud tedy nebudete odkazovat na vložené dokumenty samostatně, bude optimální použít tento návrh schématu.

Jedna k mnoha

Pro tento vztah se data v jedné databázi vztahují k datům v jiné databázi. Můžete mít například databázi pro uživatele a jinou pro příspěvky. Pokud tedy uživatel vytvoří příspěvek, je zaznamenán s ID uživatele.

Uživatelské schéma

{ 
    Full_name: “John Doh”,
    User_id: 1518787459607.0
}

Schéma příspěvků

{
    "_id" : ObjectId("5aa136f0789cf124388c1955"),
    "postTime" : "16:13",
    "postDate" : "8/3/2018",
    "postOwnerNames" : "John Doh",
    "postOwner" : 1518787459607.0,
    "postId" : "1520514800139"
}

Výhodou tohoto návrhu schématu je, že dokumenty jsou považovány za samostatné (lze vybrat samostatně). Další výhodou je, že tento design umožňuje uživatelům různých ID sdílet informace ze schématu příspěvků (odtud název One-to-Many) a někdy to může být schéma „N-to-N“ - v podstatě bez použití spojení tabulek. Omezení tohoto návrhu schématu spočívá v tom, že pro načtení nebo výběr dat ve druhé kolekci musíte provést alespoň dva dotazy.

Jak modelovat data bude tedy záviset na vzoru přístupu aplikace. Kromě toho musíte vzít v úvahu návrh schématu, o kterém jsme hovořili výše.

Optimalizační techniky pro návrh schématu

  1. V co největší míře používejte vkládání dokumentů, protože to snižuje počet dotazů, které musíte spustit pro konkrétní sadu dat.

  2. Denormalizaci nepoužívejte pro dokumenty, které jsou často aktualizovány. Pokud bude pole často aktualizováno, pak bude úkolem najít všechny instance, které je třeba aktualizovat. To bude mít za následek pomalé zpracování dotazů, a tím pádem i přesilování výhod spojených s denormalizací.

  3. Pokud je potřeba načíst dokument samostatně, pak není nutné používat vkládání, protože provádění složitých dotazů, jako je agregované zřetězení, trvá déle.

  4. Pokud je pole dokumentů, které chcete vložit, dostatečně velké, nevkládejte je. Růst pole by měl mít alespoň vázaný limit.

Správné indexování

Toto je kritičtější část ladění výkonu a vyžaduje, aby člověk měl komplexní znalosti o aplikačních dotazech, poměru čtení a zápisu a o tom, kolik volné paměti má váš systém. Pokud použijete index, pak dotaz prohledá index a ne kolekci.

Vynikající index je takový, který zahrnuje všechna pole prohledaná dotazem. To se nazývá složený index.

Chcete-li vytvořit jeden index pro pole, můžete použít tento kód:

db.collection.createIndex({“fields”: 1})

V případě složeného indexu vytvořte indexování:

db.collection.createIndex({“filed1”: 1, “field2”:  1})

Kromě rychlejšího dotazování pomocí indexování je zde další výhoda dalších operací, jako je řazení, vzorky a limit. Pokud například navrhnu své schéma jako {f:1, m:1}, mohu kromě hledání jako

provést další operaci
db.collection.find( {f: 1} ).sort( {m: 1} )

Čtení dat z paměti RAM je efektivnější než čtení stejných dat z disku. Z tohoto důvodu se vždy doporučuje zajistit, aby se váš index zcela vešel do paměti RAM. Chcete-li získat aktuální indexSize vaší kolekce, spusťte příkaz :

db.collection.totalIndexSize()

Získáte hodnotu jako 36864 bajtů. Tato hodnota by také neměla zabírat velké procento celkové velikosti paměti RAM, protože musíte uspokojit potřeby celé pracovní sady serveru.

Efektivní dotaz by měl také zvýšit selektivitu. Selektivitu lze definovat jako schopnost dotazu zúžit výsledek pomocí indexu. Chcete-li být přesnější, měly by vaše dotazy omezit počet možných dokumentů s indexovaným polem. Selektivita je většinou spojena se složeným indexem, který zahrnuje pole s nízkou selektivitou a další pole. Pokud máte například tato data:

{ _id: ObjectId(), a: 6, b: "no", c: 45 }
{ _id: ObjectId(), a: 7, b: "gh", c: 28 }
{ _id: ObjectId(), a: 7, b: "cd", c: 58 }
{ _id: ObjectId(), a: 8, b: "kt", c: 33 }

Dotaz {a:7, b:“cd”} prohledá 2 dokumenty a vrátí 1 odpovídající dokument. Pokud jsou však data pro hodnotu a rovnoměrně rozložena, tj.

{ _id: ObjectId(), a: 6, b: "no", c: 45 }
{ _id: ObjectId(), a: 7, b: "gh", c: 28 }
{ _id: ObjectId(), a: 8, b: "cd", c: 58 }
{ _id: ObjectId(), a: 9, b: "kt", c: 33 }

Dotaz {a:7, b:“cd”} naskenuje 1 dokument a vrátí tento dokument. Bude to tedy trvat kratší dobu než první datová struktura.

ClusterControlSingle Console pro celou vaši databázovou infrastrukturu Zjistěte, co je ještě nového v ClusterControl Nainstalujte ClusterControl ZDARMA

Zajišťování zdrojů

Nedostatečná paměť, RAM a další provozní parametry mohou drasticky snížit výkon MongoDB. Pokud je například počet uživatelských připojení velmi velký, bude to bránit schopnosti serverové aplikace zpracovávat požadavky včas. Jak je uvedeno v části Klíčové věci ke sledování v MongoDB, můžete získat přehled o tom, které omezené zdroje máte a jak je můžete škálovat, aby vyhovovaly vašim specifikacím. U velkého počtu souběžných požadavků aplikací bude databázový systém zahlcen, aby držel krok s poptávkou.

Prodleva replikace

Někdy si můžete všimnout, že některá data ve vaší databázi chybí nebo když něco smažete, objeví se znovu. Jakkoli můžete mít dobře navržené schéma, vhodné indexování a dostatek zdrojů, na začátku vaše aplikace poběží hladce bez jakýchkoliv zádrhelů, ale pak v určitém okamžiku zaznamenáte posledně zmíněné problémy. MongoDB spoléhá na koncept replikace, kde jsou data redundantně kopírována, aby splňovala určitá kritéria návrhu. Předpokladem je, že proces je okamžitý. Může však dojít k určitému zpoždění, které může být způsobeno selháním sítě nebo neošetřenými chybami. Stručně řečeno, mezi dobou zpracování operace na primárním uzlu a dobou, kdy bude aplikována v sekundárním uzlu, bude velká mezera.

Neúspěchy se zpožděním replik

  1. Nekonzistentní údaje. To je spojeno zejména s operacemi čtení, které jsou distribuovány napříč sekundárními servery.

  2. Je-li lag gap dostatečně velký, může být na primárním uzlu mnoho nereplikovaných dat a bude nutné je sladit v sekundárním uzlu. V určitém okamžiku to může být nemožné, zvláště když nelze obnovit primární uzel.

  3. Pokud se nepodaří obnovit primární uzel, může to donutit spustit uzel s daty, která nejsou aktuální, a následně může zahodit celou databázi, aby se primární uzel obnovil.

Příčiny selhání sekundárního uzlu

  1. Překonání primárního výkonu nad sekundárním, pokud jde o CPU, disk IOPS a síťové I/O specifikace.

  2. Složité operace zápisu. Například příkaz jako

    db.collection.update( { a: 7}  , {$set: {m: 4} }, {multi: true} )

    Primární uzel zaznamená tuto operaci do oplogu dostatečně rychle. Sekundární uzel však musí tyto operace načíst, načíst do RAM jakýkoli index a datové stránky, aby splnil některé specifikace kritérií, jako je id. Vzhledem k tomu, že to musí udělat dostatečně rychle, aby udrželo rychlost, kterou operace provádí primární uzel, pokud je počet operací dostatečně velký, dojde k očekávanému zpoždění.

  3. Uzamčení sekundáru při vytváření zálohy. V tomto případě můžeme zapomenout deaktivovat primární, takže bude pokračovat ve svých operacích jako obvykle. V době, kdy bude zámek uvolněn, bude mít zpoždění replikace velkou mezeru, zejména pokud se jedná o zálohování velkého množství dat.

  4. Budování indexu. Pokud se v sekundárním uzlu vytvoří index, všechny ostatní operace s ním spojené jsou zablokovány. Pokud je index dlouhotrvající, dojde k škytavce zpoždění replikace.

  5. Nepřipojený sekundární. Někdy může sekundární uzel selhat kvůli odpojení sítě, což má za následek zpoždění replikace, když je znovu připojen.

Jak minimalizovat zpoždění replikace

  • Kromě toho, že vaše kolekce obsahuje pole _id, použijte jedinečné indexy. Je to proto, aby se zabránilo úplnému selhání procesu replikace.

  • Zvažte jiné typy záloh, jako jsou snímky k určitému okamžiku a soubory systému, které nutně nevyžadují zamykání.

  • Vyhněte se vytváření velkých indexů, protože způsobují operace blokování na pozadí.

  • Udělejte sekundární dostatečně výkonný. Pokud je operace zápisu lehká, bude použití podvýkonových sekundárních zařízení ekonomické. Ale pro velké zatížení zápisu může sekundární uzel zaostávat za primárním. Aby byl sekundární uzel více seknutý, měl by mít dostatečnou šířku pásma, aby pomohl číst oplogy dostatečně rychle, aby si udržely svou rychlost u primárního uzlu.

Efektivní techniky dotazování

Kromě vytváření indexovaných dotazů a používání selektivity dotazů, jak je uvedeno výše, existují další koncepty, které můžete použít k upevnění a zefektivnění dotazů.

Optimalizace vašich dotazů

  1. Pomocí skrytého dotazu. Krytý dotaz je takový, který je vždy zcela uspokojen indexem, a proto nemusí zkoumat žádný dokument. Pokrytý dotaz by proto měl mít všechna pole jako součást indexu a následně by měl výsledek obsahovat všechna tato pole.

    Podívejme se na tento příklad:

    {_id: 1, product: { price: 50 }

    Pokud pro tuto kolekci vytvoříme index jako

    {“product.price”: 1} 

    Pokud vezmeme v úvahu operaci hledání, pak tento index pokryje tento dotaz;

    db.collection.find( {“product.price”: 50}, {“product.price”: 1, _id: 0}  )

    a vraťte pouze pole product.price a hodnotu.

  2. Pro vložené dokumenty použijte tečkovou notaci (.). Tečkový zápis pomáhá při přístupu k prvkům pole a polím vloženého dokumentu.

    Přístup k poli:

    {
       prices: [12, 40, 100, 50, 40]  
    }

    Chcete-li například určit čtvrtý prvek, můžete napsat tento příkaz:

    “prices.3”

    Přístup k poli objektů:

    {
    
       vehicles: [{name: toyota, quantity: 50},
                 {name: bmw, quantity: 100},
                 {name: subaru, quantity: 300}                    
    } 

    Chcete-li zadat pole názvu v poli vozidel, můžete použít tento příkaz

    “vehicles.name”
  3. Zkontrolujte, zda je dotaz pokryt. K tomu použijte db.collection.explain(). Tato funkce poskytne informace o provádění dalších operací -např. db.collection.explain().aggregate(). Chcete-li se dozvědět více o funkci vysvětlení, můžete se podívat na vysvětlení ().

Obecně platí, že nejvyšší technikou, pokud jde o dotazování, je použití indexů. Dotazování pouze na index je mnohem rychlejší než dotazování na dokumenty mimo index. Mohou se vejít do paměti, a proto jsou k dispozici spíše v RAM než na disku. Díky tomu je lze snadno a rychle načíst z paměti.


  1. klient mongodb verze 3.0.0 robomongo mongovue

  2. Přehled WiredTiger Storage Engine pro MongoDB

  3. Redis seznamy

  4. Jak znovu použít připojení mongodb prostřednictvím Promise