I min tidligere blog, Sådan bruger du MongoDB-datamodellering til at forbedre gennemstrømningsoperationer, diskuterede vi de 2 store datamodelleringsforhold, nemlig indlejring og reference. Skalerbarheden af MongoDB er ret afhængig af dens arkitektur og for at være specifik datamodellering. Når du designer en NoSQL DBM, er hovedpunktet at overveje at sikre skemaløse dokumenter udover et lille antal samlinger med henblik på nem vedligeholdelse. God dataintegritet, vedtagelse af datavalidering gennem nogle definerede regler før lagring tilskyndes. En databasearkitektur og -design bør normaliseres og dekomponeres i flere små samlinger som en måde at undgå datagentagelse, forbedre dataintegriteten og gøre det nemt med genfindingsmønstre. Med dette på plads er du i stand til at forbedre datakonsistensen, atomiciteten, holdbarheden og integriteten af din database.
Datamodellering er ikke en eftertanke i en applikationsudviklingsfase, men en indledende overvejelse, da mange applikationsfacetter faktisk realiseres under datamodelleringsfasen. I denne artikel vil vi diskutere, hvilke faktorer der skal tages i betragtning under datamodellering og se, hvordan de generelt påvirker en databases ydeevne.
Mange gange bliver du nødt til at implementere en klynge af din database som en måde at øge datatilgængeligheden på. Med en veldesignet datamodel kan du distribuere aktiviteter til en sharded cluster mere effektivt og dermed reducere gennemstrømningsoperationerne rettet mod en enkelt mongod-instans. De vigtigste faktorer at overveje i datamodellering omfatter:
- Skalerbarhed
- Atomicitet
- Ydeevne og dataforbrug
- Sharding
- Indeksering
- Lagringsoptimering
- Dokumentstruktur og vækst
- Datas livscyklus
1. Skalerbarhed
Dette er en stigning i arbejdsbyrden for en applikation drevet af øget trafik. Mange applikationer har altid en forventning om stigningen i antallet af brugere. Når der er så mange brugere, der betjenes af en enkelt databaseinstans, lever ydeevnen ikke altid op til forventningerne. Som database manager har du således mandat til at designe denne DBM således, at samlinger og dataentiteter modelleres ud fra applikationens nuværende og fremtidige krav. Databasestrukturen bør generelt være præsentabel for at gøre processen med replikering og sharding nemmere. Når du har flere shards, er skriveoperationerne fordelt mellem disse shards, således at for enhver dataopdatering udføres det inden for shard'en, der indeholder disse data i stedet for at slå op i et enkelt stort sæt data for at foretage en opdatering.
2. Atomicitet
Dette refererer til den succesfulde eller fiasko for en operation som en enkelt enhed. For eksempel kan du have en læseoperation, der involverer en sorteringsoperation efter at have hentet resultatet. Hvis sorteringsoperationen ikke håndteres korrekt, vil hele operationen derfor ikke fortsætte til næste trin.
Atomtransaktioner er serier af operationer, der hverken er delelige eller reducerbare, og derfor forekommer som enkelte enheder eller mislykkes som en enkelt operation. MongoDB-versioner før 4.0 understøtter skriveoperationer som atomprocesser på et enkelt dokumentniveau. Med version 4.0 kan man nu implementere multi-dokument transaktioner. En datamodel, der forbedrer atomoperationer, har en tendens til at have en fantastisk ydeevne med hensyn til latenstid. Latency er simpelthen den varighed, inden for hvilken en operationsanmodning sendes, og hvornår et svar returneres fra databasen. For at være seccant er det nemt at opdatere data, som er indlejret i et enkelt dokument i stedet for et, der refereres til.
Lad os for eksempel overveje datasættet nedenfor
{
childId : "535523",
studentName : "James Karanja",
parentPhone : 704251068,
age : 12,
settings : {
location : "Embassy",
address : "420 01",
bus : "KAZ 450G",
distance : "4"
}
}
Hvis vi vil opdatere alderen ved at øge den med 1 og ændre placeringen til London, kunne vi gøre:
db.getCollection(‘students’).update({childId: 535523},{$set:{'settings.location':'London'}, $inc:{age:1}}).
Hvis f.eks. $set-operationen mislykkes, vil $inc-operationen automatisk ikke blive implementeret, og generelt mislykkes hele operationen.
På den anden side, lad os overveje refererede data, sådan at der er 2 samlinger, den ene for studerende og den anden for indstillinger.
Elevsamling
{
childId : "535523",
studentName : "James Karanja",
parentPhone : 704251068,
age : 12
}
Indstillingssamling
{
childId : "535523",
location : "Embassy",
address : "420 01",
bus : "KAZ 450G",
distance : "4"
}
I dette tilfælde kan du opdatere alders- og placeringsværdierne med separate skriveoperationer .i.e
db.getCollection(‘students’).update({childId: 535523},{$inc:{age:1}})
db.getCollection('settings’).update({childId: 535523 } , {$set: { 'settings.location':'London'}})
Hvis en af operationerne mislykkes, påvirker det ikke nødvendigvis den anden, da de udføres som forskellige enheder.
Transaktioner for flere dokumenter
Med MongoDB version 4.0 kan du nu udføre flere dokumenttransaktioner for replikasæt. Dette forbedrer ydeevnen, da operationerne er udstedt til en række samlinger, databaser og dokumenter til hurtig behandling. Når en transaktion er blevet begået, gemmes dataene, mens hvis noget går galt, og en transaktion mislykkes, kasseres de ændringer, der var blevet foretaget, og transaktionen vil generelt blive afbrudt. Der vil ikke være nogen opdatering til replikasættene under transaktionen, da handlingen kun er synlig udenfor, når transaktionen er fuldt ud begået.
Så meget som du kan opdatere flere dokumenter i flere transaktioner, kommer det med et tilbageslag af reduceret ydeevne sammenlignet med enkelt dokumentskrivning. Desuden understøttes denne tilgang kun for WiredTiger-lagringsmotoren, og er derfor en ulempe for In-Memory- og MMAPv1-lagringsmotorerne.
3. Ydelse og dataforbrug
Applikationer er designet forskelligt til at opfylde forskellige formål. Der er nogle, der kun tjener til de aktuelle data som vejrnyhedsapplikationer. Afhængigt af strukturen af en applikation, bør man være i stand til at designe en korrespondent optimal database til at servere den nødvendige use case. For eksempel, hvis man udvikler en applikation, der henter de seneste data fra databasen, vil brug af en begrænset samling være den bedste mulighed. En begrænset samling forbedrer driften med høj gennemløb ligesom en buffer, således at når den tildelte plads udnyttes, overskrives de ældste dokumenter, og dokumenterne kan hentes i den rækkefølge, de blev indsat. I betragtning af hentning af indsættelsesordre vil der ikke være behov for at bruge indeksering, og fravær af en indeksoverhead vil ligeledes forbedre skrivegennemstrømningen. Med en begrænset samling er de tilknyttede data ret små, da de kan opbevares i RAM i nogen tid. Tidsmæssige data i dette tilfælde er gemt i cachen, som er ret læst end at blive skrevet ind i, hvilket gør læseoperationen ret hurtig. Den begrænsede samling kommer dog med nogle ulemper, såsom at du ikke kan slette et dokument, medmindre du slipper hele samlingen, enhver ændring af størrelsen på et dokument vil mislykkes i operationen, og endelig er det ikke muligt at sønderdele en begrænset samling.
Forskellige facetter er integreret i datamodelleringen af en database afhængigt af brugsbehovet. Som det ses, vil rapportapplikationer have en tendens til at være mere læseintensive, og designet bør derfor være på en måde, der forbedrer læsegennemstrømningen.
4. Sharding
Ydeevne gennem horisontal skalering kan forbedres ved sharding, da læse- og skrivebelastningerne er fordelt mellem klyngemedlemmerne. Implementering af en klynge af shards har en tendens til at opdele databasen i flere små samlinger med distribuerede dokumenter afhængigt af en shard-nøgle. Du bør vælge en passende shard-nøgle, som kan forhindre forespørgselsisolering udover at øge skrivekapaciteten. En bedre udvælgelse involverer generelt et felt, der er til stede i alle dokumenter inden for den målrettede samling. Med sharding er der øget lagerplads, da efterhånden som dataene vokser, etableres flere shards til at indeholde en undergruppe af denne klynge.
5. Indeksering
Indeksering er en af de bedste metoder til at forbedre skrivearbejdsbyrden, især hvor felterne forekommer i alle dokumenter. Når man laver indeksering, bør man overveje, at hvert indeks vil kræve 8KB dataplads. Ydermere, når indekset er aktivt, vil det forbruge noget diskplads og hukommelse, og derfor bør det spores til kapacitetsplanlægning.
Severalnines Bliv en MongoDB DBA - Bring MongoDB to ProductionLær om, hvad du skal vide for at implementere, overvåge, administrere og skalere MongoDBDownload gratis6. Lageroptimering
Mange små dokumenter inden for en samling vil have en tendens til at tage mere plads, end når du har nogle få dokumenter med underindlejrede dokumenter. Ved modellering bør man derfor gruppere de relaterede data før lagring. Med nogle få dokumenter kan en databaseoperation udføres med få forespørgsler og dermed reduceret tilfældig diskadgang, og der vil være færre tilknyttede nøgleposter i det tilsvarende indeks. Overvejelser i dette tilfælde vil derfor være:brug indlejring for at få færre dokumenter, hvilket igen reducerer overhead pr. dokument. Brug kortere feltnavne, hvis færre felter er involveret i en samling for ikke at gøre dokumentoverhead væsentligt. Kortere feltnavne reducerer udtryksevnen, dvs.
{ Lname : "Briston", score : 5.9 }
vil spare 9 bytes pr. dokument i stedet for at bruge
{ last_name : "Briston", high_score: 5.9 }
Brug eksplicit feltet _id. Som standard tilføjer MongoDB-klienter et _id-felt til hvert dokument ved at tildele et unikt 12-byte ObjectId til dette felt. Desuden vil _id-feltet blive indekseret. Hvis dokumenterne er ret små, vil dette scenarie stå for en betydelig mængde plads i det samlede dokumentnummer. Til lageroptimering har du lov til at angive værdien for _id-feltet eksplicit, når du indsætter dokumenter i en samling. Sørg dog for, at værdien er entydigt identificeret, fordi den fungerer som en primær nøgle for dokumenter i samlingen.
7. Dokumentstruktur og vækst
Dette sker som et resultat af push-operationen, hvor underdokumenter skubbes ind i et array-felt, eller når nye felter tilføjes til et eksisterende dokument. Dokumentvækst har nogle tilbageslag, dvs. for en begrænset samling, hvis størrelsen ændres, vil operationen automatisk mislykkes. For en MMAPv1-lagringsmotor vil versioner før 3.0 flytte dokumentet til disken, hvis dokumentstørrelsen overskrides. Men senere versioner fra og med 3.0 er der et koncept med Power of 2 Sized Allocations, som reducerer chancerne for sådanne genallokeringer og tillader effektiv genbrug af den frigjorte postplads. Hvis du forventer, at dine data vokser, kan det være en god idé at omstrukturere din datamodel til at bruge referencer mellem data i særskilte dokumenter i stedet for at bruge en denormaliseret datamodel. For at undgå dokumentvækst kan du også overveje at bruge en præ-allokeringsstrategi.
8. Datalivscyklus
For et program, der kun bruger de nyligt indsatte dokumenter, kan du overveje at bruge en begrænset samling, hvis funktioner er blevet diskuteret ovenfor.
Du kan også indstille Time to Live-funktionen for din samling. Dette er ganske anvendeligt for adgangstokens i funktionen til nulstilling af adgangskode til en applikation.
Time To Live (TTL)
Dette er en indsamlingsindstilling, der gør det muligt for mongod automatisk at fjerne data efter en specificeret varighed. Som standard anvendes dette koncept for maskingenererede hændelsesdata, logfiler og sessionsoplysninger, som skal vare ved i en begrænset periode.
Eksempel:
db.log_events.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )
Vi har oprettet et indeks oprettet ved og angivet en expireAfterSeconds-værdi på 3600, hvilket er 1 time efter oprettelsestidspunktet. Hvis vi nu indsætter et dokument som:
db.log_events.insert( {
"createdAt": new Date(),
"logEvent": 2,
"logMessage": "This message was recorded."
} )
Dette dokument vil blive slettet efter 1 time fra tidspunktet for indsættelse.
Du kan også indstille et bestemt klokkeslæt, når du ønsker, at dokumentet skal slettes. For at gøre det skal du først oprette et indeks, dvs.:
db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )
Nu kan vi indsætte et dokument og angive tidspunktet for, hvornår det skal slettes.
db.log_events.insert( {
"expireAt": new Date(December 12, 2018 18:00:00'),
"logEvent": 2,
"logMessage": "Success!"
} )
Dette dokument slettes automatisk, når expireAt-værdien er ældre end det antal sekunder, der er angivet i expireAfterSeconds, dvs. 0 i dette tilfælde.
Konklusion
Datamodellering er en rummelig opgave for ethvert applikationsdesign for at forbedre databasens ydeevne. Før du indsætter data i din db, skal du overveje applikationsbehovene, og hvilke der er de bedste datamodelmønstre, du bør implementere. Desuden kan vigtige facetter af applikationer ikke realiseres før implementeringen af en ordentlig datamodel.