sql >> Database >  >> NoSQL >> MongoDB

Schema's plannen en beheren in MongoDB (ook al is het schemaloos)

Toen MongoDB werd geïntroduceerd, was het belangrijkste kenmerk dat werd benadrukt het vermogen om "schemaloos" te zijn. Wat betekent het? Het betekent dat men JSON-documenten, elk met een andere structuur, in dezelfde collectie kan opslaan. Dit is best gaaf. Maar het probleem begint wanneer u de documenten moet ophalen. Hoe weet u of een opgehaald document een bepaalde structuur heeft, of het een bepaald veld bevat of niet? U moet door alle documenten bladeren en naar dat specifieke veld zoeken. Daarom is het handig om het MongoDB-schema zorgvuldig te plannen, vooral voor de grote applicaties.

Als het op MongoDB aankomt, is er geen specifieke manier om het schema te ontwerpen. Het hangt allemaal af van uw toepassing en hoe uw toepassing de gegevens gaat gebruiken. Er zijn echter enkele algemene praktijken die u kunt volgen bij het ontwerpen van uw databaseschema. Hier zal ik deze praktijken en hun voor- en nadelen bespreken.

Een-op-enkele modellering (inbedding)

Dit ontwerp is een heel goed voorbeeld van het insluiten van documenten. Beschouw dit voorbeeld van een Person-verzameling om deze modellering te illustreren.

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

Voordelen:

  • Je kunt alle informatie in één zoekopdracht krijgen.

Nadelen:

  • Ingesloten gegevens zijn volledig afhankelijk van het bovenliggende document. U kunt de ingesloten gegevens niet onafhankelijk doorzoeken.
  • Beschouw het voorbeeld waarin u een taakvolgsysteem maakt met deze benadering. Vervolgens gaat u alle taken die specifiek zijn voor één persoon insluiten in de Person-verzameling. Als je een zoekopdracht wilt uitvoeren zoals:Toon me alle taken die morgen als deadline hebben. Dit kan erg moeilijk zijn, ook al is het een simpele vraag. In dit geval moet u andere benaderingen overwegen.

Een-op-veel-modellering (referentie)

Bij dit type modellering bevat het bovenliggende document de referentie-ID (ObjectID) van de onderliggende documenten. U moet joins op toepassingsniveau gebruiken (twee documenten combineren nadat u ze op toepassingsniveau uit de database hebt opgehaald) om documenten op te halen, dus geen joins op databaseniveau. Daarom wordt de belasting van een database verminderd. Beschouw dit voorbeeld:

// 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')
  ]
}

Stel dat aan elk product enkele duizenden onderdelen zijn gekoppeld. Voor dit soort databases is refereren het ideale type modellering. U plaatst de referentie-id's van alle bijbehorende onderdelen onder productdocument. Vervolgens kunt u joins op applicatieniveau gebruiken om de onderdelen voor een bepaald product te krijgen.

Voordelen:

  • Bij dit type modellering is elk onderdeel een afzonderlijk document, zodat u alle onderdeelgerelateerde query's op deze documenten kunt toepassen. U hoeft niet afhankelijk te zijn van het bovenliggende document.
  • Zeer eenvoudig om CRUD-bewerkingen (creëren, lezen, bijwerken, schrijven) op elk document afzonderlijk uit te voeren.

Nadelen:

  • Een groot nadeel van deze methode is dat je één extra query moet uitvoeren om de details van het onderdeel te krijgen. Zodat u joins op toepassingsniveau met het productdocument kunt uitvoeren om de benodigde resultatenset te krijgen. Het kan dus leiden tot een daling van de DB-prestaties.
Multiplenines Word een MongoDB DBA - MongoDB naar productie brengenLeer over wat u moet weten om MongoDB gratis te implementeren, bewaken, beheren en schalen

Modellen van één tot miljoenen (verwijzing naar ouders)

Wanneer u tonnen gegevens in elk document moet opslaan, kunt u geen van de bovenstaande benaderingen gebruiken omdat MongoDB een maximale grootte heeft van 16 MB per document. Een perfect voorbeeld van dit soort scenario kan een gebeurtenisregistratiesysteem zijn dat logboeken verzamelt van verschillende soorten machines en deze opslaat in logboeken en machineverzamelingen.

Hier kunt u niet eens nadenken over het gebruik van de Embedding-aanpak, waarbij alle loggegevens voor een bepaalde machine in één document worden opgeslagen. Dit komt omdat in slechts een paar uur de documentgrootte meer dan 16 MB zal zijn. Zelfs als u alleen referentie-ID's van alle logbestanden opslaat, raakt u nog steeds de limiet van 16 MB, omdat sommige machines miljoenen logberichten op één dag kunnen genereren.

Dus in dit geval kunnen we de ouderreferentiebenadering gebruiken. In deze benadering zullen we, in plaats van referentie-id's van onderliggende documenten in het bovenliggende document op te slaan, de referentie-id van het bovenliggende document opslaan in alle onderliggende documenten. Dus voor ons voorbeeld zullen we ObjectID van de machine opslaan in Logboeken. Beschouw dit voorbeeld:

// 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
}

Stel dat u de meest recente 3000 logs van Machine 127.66.0.4 wilt vinden:

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

Tweerichtingsreferentie

Bij deze benadering slaan we de referenties aan beide kanten op, wat betekent dat de referentie van de ouder wordt opgeslagen in het onderliggende document en de referentie van het kind wordt opgeslagen in het bovenliggende document. Dit maakt het zoeken relatief eenvoudig in een tot veel modellen. We kunnen bijvoorbeeld zoeken in zowel bovenliggende als taakdocumenten. Aan de andere kant vereist deze aanpak twee afzonderlijke zoekopdrachten om één document bij te werken.

// 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
}

Conclusie

Uiteindelijk hangt het allemaal af van uw toepassingsvereisten. U kunt het MongoDB-schema ontwerpen op een manier die het gunstigst is voor uw toepassing en u hoge prestaties levert. Hier zijn enkele samengevatte overwegingen waarmee u rekening kunt houden bij het ontwerpen van uw schema.

  1. Ontwerp het schema op basis van de gegevenstoegangspatronen van uw toepassing.
  2. Het is niet nodig om elke keer documenten in te sluiten. Combineer documenten alleen als u ze samen gaat gebruiken.
  3. Overweeg dubbele gegevens, omdat opslag tegenwoordig goedkoper is dan rekenkracht.
  4. Optimaliseer het schema voor vaker gebruik.
  5. Arrays mogen niet buiten de grenzen groeien. Als er meer dan een paar honderd onderliggende documenten zijn, sluit deze dan niet in.
  6. Geef de voorkeur aan joins op applicatieniveau boven joins op databaseniveau. Met de juiste indexering en correct gebruik van projectievelden kan het u veel tijd besparen.

  1. MongoDB Update Deep Array

  2. Meteor en DBrefs

  3. MongoDB:Hoe werk ik een enkel subelement in een array bij, waarnaar wordt verwezen door de index in de array?

  4. sudo service mongodb herstart geeft niet-herkende servicefout in ubuntu 14.0.4