Som redan skrivits finns det inga regler som den andra normala formen för SQL.
Det finns dock några bästa praxis och vanliga fallgropar relaterade till optimering för MongoDB som jag kommer att lista här.
Överanvändning av inbäddning
BSON-gränsen
I motsats till vad många tror är det inget fel med referenser. Anta att du har ett bibliotek med böcker och att du vill spåra uthyrningen. Du kan börja med en modell som denna
{
// 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"
}
]
}
Även om det finns flera problem med den här modellen, är det viktigaste inte uppenbart – det kommer att finnas ett begränsat antal uthyrningar på grund av det faktum att BSON-dokument har en storleksgräns på 16 MB.
Problem med dokumentmigrering
Det andra problemet med att lagra hyror i en array skulle vara att detta skulle orsaka relativt frekventa dokumentmigreringar, vilket är en ganska kostsam operation. BSON-dokument partitioneras aldrig och skapas med lite extra utrymme tilldelat i förväg som används när de växer. Detta extra utrymme kallas utfyllnad. När utfyllnaden överskrids flyttas dokumentet till en annan plats i datafilerna och nytt utfyllnadsutrymme tilldelas. Så frekventa tillägg av data orsakar ofta dokumentmigreringar. Därför är det bästa praxis att förhindra att frekventa uppdateringar ökar storleken på dokumentet och använda referenser istället.
Så för exemplet skulle vi ändra vår enda modell och skapa en andra. Först modellen till boken
{
_id: "9783453031456",
title:"Schismatrix",
author: "Bruce Sterling"
}
Den andra modellen för uthyrningen skulle se ut så här
{
_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")
}
Samma tillvägagångssätt kan naturligtvis användas för författare eller hyrestagare.
Problemet med övernormalisering
Låt oss titta tillbaka en tid. En utvecklare skulle identifiera de enheter som är inblandade i ett affärscase, definiera deras egenskaper och relationer, skriva motsvarande enhetsklasser, slå huvudet mot väggen i några timmar för att få det tredubbla inre-yttre-över-och-bortom JOIN-arbete som krävs för användningsfallet och alla levde lyckliga i alla sina dagar. Så varför använda NoSQL i allmänhet och MongoDB i synnerhet? För ingen levde lycklig i alla sina dagar. Detta tillvägagångssätt skalar fruktansvärt och nästan uteslutande det enda sättet att skala är vertikalt.
Men den största skillnaden med NoSQL är att du modellerar din data enligt de frågor du behöver för att få svar på.
Med det sagt, låt oss titta på en typisk n:m-relation och ta relationen från författare till böcker som vårt exempel. I SQL skulle du ha tre tabeller:två för dina enheter (böcker och författare ) och en för relationen (Vem är författaren till vilken bok? ). Naturligtvis kan du ta dessa tabeller och skapa deras motsvarande samlingar. Men eftersom det inte finns några JOINs i MongoDB, skulle du behöva tre frågor (en för den första enheten, en för dess relationer och en för de relaterade enheterna) för att hitta de relaterade dokumenten för en entitet. Detta skulle inte vara meningsfullt, eftersom tre-tabellsmetoden för n:m-relationer uppfanns specifikt för att övervinna de strikta scheman som SQL-databaser tillämpar. Eftersom MongoDB har ett flexibelt schema, skulle den första frågan vara var relationen ska lagras, för att behålla problemen. som härrör från överanvändning av inbäddning i åtanke. Eftersom en författare kan skriva en hel del böcker under de kommande åren, men författarskapet till en bok sällan, om alls, förändras, är svaret enkelt:Vi lagrar författarna som en referens till författarna i böckernas data
{
_id: "9783453526723",
title: "The Difference Engine",
authors: ["idOfBruceSterling","idOfWilliamGibson"]
}
Och nu kan vi hitta författarna till den boken genom att göra två frågor:
var book = db.books.findOne({title:"The Difference Engine"})
var authors = db.authors.find({_id: {$in: book.authors})
Jag hoppas att ovanstående hjälper dig att bestämma när du faktiskt ska "dela" dina samlingar och att komma runt de vanligaste fallgroparna.
Slutsats
När det gäller dina frågor, här är mina svar
- Som tidigare skrivit:Nej , men att ha de tekniska begränsningarna i åtanke bör ge dig en uppfattning om när det kan vara vettigt.
- Det är inte dåligt – så länge det passar dina användningsfall . Om du har en given kategori och dess
_id
, är det lätt att hitta relaterade produkter. När du laddar produkten kan du enkelt få kategorierna den tillhör, även effektivt, som_id
är indexerad som standard. - Jag har ännu inte hittat ett användningsfall som inte kan göras med MongoDB, även om vissa saker kan bli lite mer komplicerade med MongoDB. Vad du bör göra imho är att ta summan av dina funktionella och icke-funktionella krav och kontrollera om fördelarna överväger nackdelarna. Min tumregel:om något av "skalbarhet" eller "hög tillgänglighet/automatisk failover" finns på din kravlista, är MongoDB värt mer än en titt.