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
- 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.
- 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. - 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.