sql >> Database teknologi >  >> NoSQL >> MongoDB

Planlægning og styring af skemaer i MongoDB (selv om det er skemaløst)

Da MongoDB blev introduceret, var hovedfunktionen fremhævet dens evne til at være "skemaløs". Hvad betyder det? Det betyder, at man kan gemme JSON-dokumenter, hver med forskellig struktur, i samme samling. Det her er ret fedt. Men problemet starter, når du skal hente dokumenterne. Hvordan fortæller man, at et hentet dokument har en bestemt struktur, eller om det indeholder et bestemt felt eller ej? Du skal gennemgå alle dokumenterne og søge efter det pågældende felt. Det er derfor, det er nyttigt at planlægge MongoDB-skemaet omhyggeligt, især for de store applikationer.

Når det kommer til MongoDB, er der ingen specifik måde at designe skemaet på. Det hele afhænger af din applikation og hvordan din applikation vil bruge dataene. Der er dog nogle almindelige fremgangsmåder, som du kan følge, mens du designer dit databaseskema. Her vil jeg diskutere disse fremgangsmåder og deres fordele og ulemper.

En-til-få-modellering (indlejring)

Dette design er et meget godt eksempel på indlejring af dokumenter. Overvej dette eksempel på en personsamling for at illustrere denne modellering.

{
  name: "Amy Cooper",
  hometown: "Seoul",
  addresses: [
    { city: 'New York', state: 'NY', cc: 'USA' },
    { city: 'Jersey City', state: 'NJ', cc: 'USA' }
  ]
}

Fordele:

  • Du kan få alle oplysningerne i en enkelt forespørgsel.

Ulemper:

  • Indlejrede data er fuldstændig afhængige af det overordnede dokument. Du kan ikke søge i de indlejrede data uafhængigt.
  • Overvej eksemplet, hvor du opretter et opgavesporingssystem ved hjælp af denne tilgang. Derefter vil du indlejre alle opgaver, der er specifikke for én person, i Personsamlingen. Hvis du vil affyre en forespørgsel som:Vis mig alle opgaver, der har i morgen som deadline. Dette kan være meget svært, selvom det er en simpel forespørgsel. I dette tilfælde bør du overveje andre fremgangsmåder.

En-til-mange-modellering (reference)

I denne type modellering vil det overordnede dokument indeholde reference-id'et (ObjectID) for de underordnede dokumenter. Du skal bruge joinforbindelser på applikationsniveau (ved at kombinere to dokumenter efter at have hentet dem fra DB på applikationsniveau) for at hente dokumenter, så ingen databaseniveau forbindes. Derfor vil belastningen på en database blive reduceret. Overvej dette eksempel:

// Parts collection
{
  _id: ObjectID(1234),
  partno: '1',
  name: ‘Intel 100 Ghz CPU',
  qty: 100,
  cost: 1000,
  price: 1050
}
// Products collection
{
  name: 'Computer WQ-1020',
  manufacturer: 'ABC Company',
  catalog_number: 1234,
  parts: [
    ObjectID(‘1234’), <- Ref. for Part No: 1
    ObjectID('2345'),
    ObjectID('3456')
  ]
}

Antag, at hvert produkt kan have flere tusinde dele tilknyttet. For denne type database er referencer den ideelle form for modellering. Du placerer reference-id'erne for alle de tilknyttede dele under produktdokumentet. Så kan du bruge sammenføjninger på applikationsniveau til at få delene til et bestemt produkt.

Fordele:

  • I denne type modellering er hver del et separat dokument, så du kan anvende alle delrelaterede forespørgsler på disse dokumenter. Ingen grund til at være afhængig af overordnet dokument.
  • Meget let at udføre CRUD-operationer (Opret, Læs, Opdater, Skriv) på hvert dokument uafhængigt.

Ulemper:

  • En stor ulempe ved denne metode er, at du skal udføre en ekstra forespørgsel for at få deldetaljerne. Så du kan udføre sammenføjninger på applikationsniveau med produktdokumentet for at få det nødvendige resultat. Så det kan føre til et fald i DB-ydeevne.
Severalnines Bliv en MongoDB DBA - Bring MongoDB to ProductionFå flere oplysninger om, hvad du skal vide for at implementere, overvåge, administrere og skalere MongoDBDownload gratis

One-to-Millions-modellering (forældrereference)

Når du skal gemme tonsvis af data i hvert dokument, kan du ikke bruge nogen af ​​ovenstående fremgangsmåder, fordi MongoDB har en størrelsesbegrænsning på 16 MB pr. dokument. Et perfekt eksempel på denne form for scenarie kan være et hændelseslogningssystem, som indsamler logfiler fra forskellige typer maskiner og gemmer dem i logs og maskinsamlinger.

Her kan du ikke engang tænke på at bruge Embedding-tilgangen, som gemmer alle logoplysninger for en bestemt maskine i et enkelt dokument. Dette skyldes, at dokumentstørrelsen på kun få timer vil være mere end 16 MB. Selvom du kun gemmer reference-id'er for alle logdokumenterne, vil du stadig opbruge grænsen på 16 MB, fordi nogle maskiner kan generere millioner af logbeskeder på en enkelt dag.

Så i dette tilfælde kan vi bruge forældrereferencemetoden. I denne tilgang vil vi i stedet for at gemme reference-id'er for underordnede dokumenter i det overordnede dokument gemme reference-id'et for det overordnede dokument i alle underordnede dokumenter. Så for vores eksempel gemmer vi maskinens ObjectID i Logs-dokumenter. Overvej dette eksempel:

// Machines collection
{
  _id : ObjectID('AAA'),
  name : 'mydb.example.com',
  ipaddr : '127.66.0.4'
}
// Logs collection
{
  time : ISODate("2015-09-02T09:10:09.032Z"),
  message : 'WARNING: CPU usage is critical!',
  host: ObjectID('AAA')       -> references Machine document
}

Antag, at du vil finde de seneste 3000 logfiler af Machine 127.66.0.4:

machine = db.machines.findOne({ipaddr : '127.66.0.4'});
msgs = db.logmsg.find({machine: machine._id}).sort({time : -1}).limit(3000).toArray()

Tovejsreference

I denne tilgang gemmer vi referencerne på begge sider, hvilket betyder, at forældrenes reference vil blive gemt i underordnet dokument, og barnets reference vil blive gemt i overordnet dokument. Dette gør søgning relativt let i en til mange modellering. For eksempel kan vi søge på både overordnede og opgavedokumenter. På den anden side kræver denne tilgang to separate forespørgsler for at opdatere ét dokument.

// person
{
  _id: ObjectID("AAAA"),
  name: "Bear",
  tasks [ 
    ObjectID("AAAD"),
    ObjectID("ABCD"), -> Reference of child document
    ObjectID("AAAB")
  ]
}
// tasks
{
  _id: ObjectID("ABCD"),
  description: "Read a Novel",
  due_date:  ISODate("2015-11-01"),
  owner: ObjectID("AAAA") -> Reference of parent document
}

Konklusion

I sidste ende afhænger det hele af dine ansøgningskrav. Du kan designe MongoDB-skemaet på en måde, der er den mest fordelagtige for din applikation og giver dig høj ydeevne. Her er nogle opsummerede overvejelser, som du kan overveje, når du designer dit skema.

  1. Design skemaet baseret på din applikations dataadgangsmønstre.
  2. Det er ikke nødvendigt at indlejre dokumenter hver gang. Kombiner kun dokumenter, hvis du skal bruge dem sammen.
  3. Overvej duplikering af data, fordi lagring er billigere end computerkraft i dag.
  4. Optimer skemaet til hyppigere brug.
  5. Arrays bør ikke vokse ud af bunden. Hvis der er mere end et par hundrede underordnede dokumenter, så lad være med at integrere det.
  6. Foretrækker joinforbindelser på applikationsniveau frem for joinforbindelser på databaseniveau. Med korrekt indeksering og korrekt brug af projektionsfelter kan det spare dig for en masse tid.

  1. Korrekt måde at importere json-fil til mongo

  2. Effektiv måde at ændre sæt medlemsopdatering

  3. Hvordan implementerer du et primært ID med automatisk stigning i MongoDB?

  4. redis lua script vs. enkeltopkald