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

MongoDB (noSQL), kdy rozdělit kolekce

Jak již bylo napsáno, neexistují žádná pravidla jako druhá normální forma pro SQL.

Existují však některé osvědčené postupy a běžná úskalí související s optimalizací pro MongoDB, které zde uvedu.

Nadměrné používání vkládání

Limit BSON

Na rozdíl od všeobecného přesvědčení není na odkazech nic špatného. Předpokládejme, že máte knihovnu knih a chcete sledovat výpůjčky. Můžete začít s takovým modelem

{
  // We use ISBN for its uniqueness 
  _id: "9783453031456"
  title: "Schismatrix",
  author: "Bruce Sterling",
  rentals: [
    {
      name:"Markus Mahlberg,
      start:"2015-05-05T03:22:00Z",
      due:"2015-05-12T12:00:00Z"
    }
  ]
}

I když je s tímto modelem několik problémů, ten nejdůležitější není zřejmý – bude k dispozici omezený počet pronájmů protože dokumenty BSON mají limit velikosti 16 MB.

Problém s migrací dokumentů

Dalším problémem s ukládáním pronájmů do pole by bylo, že by to způsobovalo poměrně časté migrace dokumentů, což je poměrně nákladná operace. Dokumenty BSON se nikdy nerozdělují na oddíly a nevytvářejí se s určitým dodatečným prostorem přiděleným předem, který se používá při jejich růstu. Tento dodatečný prostor se nazývá výplň. Když je výplň překročena, dokument se přesune na jiné místo v datových souborech a je přiděleno nové místo pro výplň. Časté přidávání dat tedy způsobuje časté migrace dokumentů. Proto je nejlepší praxí zabránit častým aktualizacím zvětšujícím velikost dokumentu a místo toho používat odkazy.

Takže pro příklad bychom změnili náš jediný model a vytvořili druhý. Nejprve model knihy

{
  _id: "9783453031456",
  title:"Schismatrix",
  author: "Bruce Sterling"
}

Druhý model pro pronájem by vypadal takto

{
  _id: new ObjectId(),
  book: "9783453031456",
  rentee: "Markus Mahlberg",
  start: ISODate("2015-05-05T03:22:00Z"),
  due: ISODate("2015-05-05T12:00:00Z"),
  returned: ISODate("2015-05-05T11:59:59.999Z")
}

Stejný přístup lze samozřejmě použít pro autora nebo nájemce.

Problém s nadměrnou normalizací

Ohlédněme se o nějaký čas zpět. Vývojář by identifikoval entity zapojené do obchodního případu, definoval jejich vlastnosti a vztahy, napsal odpovídající třídy entit, tloukl hlavou o zeď po dobu několika hodin, aby zprovoznil požadovaný trojitý vnitřní-vnější-nad-a-nad rámec JOIN. pro případ použití a všichni žili šťastně až do smrti. Proč tedy používat NoSQL obecně a MongoDB konkrétně? Protože nikdo nežil šťastně až do smrti. Tento přístup se strašně mění a téměř výlučně jediný způsob, jak škálovat, je vertikální.

Ale hlavní rozdíl NoSQL je v tom, že svá data modelujete podle otázek, na které potřebujete odpovědět.

Jak již bylo řečeno, podívejme se na typický vztah n:m a vezměme si jako příklad vztah od autorů ke knihám. V SQL byste měli 3 tabulky:dvě pro vaše entity (knihy a autoři ) a jeden pro vztah (Kdo je autorem které knihy? ). Samozřejmě můžete vzít tyto tabulky a vytvořit jejich ekvivalentní kolekce. Ale protože v MongoDB nejsou žádné JOINy, budete potřebovat tři dotazy (jeden pro první entitu, jeden pro její vztahy a jeden pro související entity), abyste našli související dokumenty entity. To by nedávalo smysl, protože třítabulkový přístup pro vztahy n:m byl speciálně vynalezen, aby překonal přísná schémata, která databáze SQL vynucují. Vzhledem k tomu, že MongoDB má flexibilní schéma, první otázkou by bylo, kam uložit vztah, aby se předešlo problémům vyplývající z nadměrného používání vkládání na mysli. Vzhledem k tomu, že autor může v nadcházejících letech napsat poměrně dost knih, ale autorství knihy se změní jen zřídka, pokud vůbec, odpověď je jednoduchá:Autory ukládáme jako odkaz na autory v datech knih

{
  _id: "9783453526723",
  title: "The Difference Engine",
  authors: ["idOfBruceSterling","idOfWilliamGibson"]
}

A nyní můžeme najít autory této knihy zadáním dvou dotazů:

var book = db.books.findOne({title:"The Difference Engine"})
var authors = db.authors.find({_id: {$in: book.authors})

Doufám, že výše uvedené vám pomůže rozhodnout se, kdy vlastně své sbírky „rozdělit“ a jak obejít nejčastější úskalí.

Závěr

Pokud jde o vaše otázky, zde jsou mé odpovědi

  1. Jak již bylo napsáno:Ne , ale pokud budete mít na paměti technická omezení, měli byste si udělat představu, kdy by to mohlo mít smysl.
  2. Není to špatné – pokud se to hodí pro vaše případy použití . Pokud máte danou kategorii a její _id , je snadné najít související produkty. Při načítání produktu můžete snadno získat kategorie, do kterých patří, a to i efektivně jako _id je ve výchozím nastavení indexováno.
  3. Ještě jsem nenašel případ použití, který nelze provést s MongoDB, ačkoli některé věci mohou být s MongoDB trochu komplikovanější. Co byste měli udělat, je vzít součet vašich funkčních a nefunkčních požadavků a ověřit, zda výhody převažují nad nevýhodami. Moje základní pravidlo:pokud je na vašem seznamu požadavků „škálovatelnost“ nebo „vysoká dostupnost/automatické převzetí služeb při selhání“, MongoDB stojí za více než pohled.



  1. Docker [Errno 111] Připojit volání se nezdařilo ('127.0.0.1', 6379)

  2. Aktualizujte více dokumentů ATOMICKY A vraťte je

  3. Jak sečtete hodnoty v rámci objektu, který je vnořeným vnořeným dokumentem v mongodb pomocí node.js?

  4. Najděte dokumenty s poli, která neobsahují dokument s konkrétní hodnotou pole v MongoDB