Te veel gegevensduplicatie in mongodb?

Ik ben nieuw in dit hele NOSQL-gedoe en ben onlangs geïntrigeerd door mongoDB. Ik ben vanaf het begin een nieuwe website aan het maken en heb besloten om MONGODB/NORM (voor C#) als mijn enige database te gebruiken. Ik heb veel gelezen over het correct ontwerpen van uw documentmodeldatabase en ik denk dat mijn ontwerp voor het grootste deel redelijk goed is uitgewerkt. Ik ben ongeveer 6 maanden op mijn nieuwe site en ik begin problemen te zien met gegevensduplicatie/synchronisatie waar ik steeds weer mee te maken krijg. Van wat ik heb gelezen, wordt dit verwacht in het documentmodel, en voor de prestaties is het logisch. D.W.Z. je plakt ingesloten objecten in je document zodat het snel te lezen is – geen joins; maar je kunt natuurlijk niet altijd embedden, dus mongodb heeft dit concept van een DbReference die in principe analoog is aan een externe sleutel in relationele DB’s.

Dus hier is een voorbeeld: ik heb gebruikers en gebeurtenissen; beide krijgen hun eigen document, gebruikers wonen evenementen bij, evenementen hebben gebruikersbezoekers. Ik besloot een lijst met gebeurtenissen met beperkte gegevens in de gebruikersobjecten in te sluiten. Ik heb een lijst met gebruikers ook in de gebeurtenisobjecten ingesloten als hun “aanwezigen”. Het probleem hier is nu dat ik de gebruikers synchroon moet houden met de lijst met gebruikers die ook is ingesloten in het gebeurtenisobject. Zoals ik het lees, lijkt dit de voorkeursbenadering te zijn, en de NOSQL-manier om dingen te doen. Het ophalen is snel, maar de fall-back is dat wanneer ik het hoofdgebruikersdocument bijwerk, ik ook naar de gebeurtenisobjecten moet gaan, mogelijk alle verwijzingen naar die gebruiker moet vinden en dat ook moet bijwerken.

Dus de vraag die ik heb is, is dit een vrij algemeen probleem waar mensen mee te maken hebben? Hoeveel moet dit probleem zijn voordat je begint te zeggen “misschien past de NOSQL-strategie niet bij wat ik hier probeer te doen”? Wanneer verandert het prestatievoordeel van het niet hoeven doen van joins in een nadeel omdat u het moeilijk vindt om gegevens in ingesloten objecten synchroon te houden en meerdere keren naar de database te lezen om dit te doen?


Antwoord 1, autoriteit 100%

Nou, dat is de afweging met documentopslag. U kunt op een genormaliseerde manier opslaan zoals elke standaard RDMS, en u moet zoveel mogelijk streven naar normalisatie. Alleen waar het een prestatiehit is, moet u de normalisatie doorbreken en uw gegevensstructuren afvlakken. De afweging is leesefficiëntie versus updatekosten.

Mongo heeft zeer efficiënte indexen die normaliseren eenvoudiger kunnen maken, zoals een traditioneel RDMS (de meeste documentopslagplaatsen bieden u dit niet gratis aan en daarom is Mongo meer een hybride in plaats van een pure documentopslag). Hiermee kunt u een relatieverzameling maken tussen gebruikers en gebeurtenissen. Het is analoog aan een surrogaattabel in een gegevensarchief in tabelvorm. Indexeer de gebeurtenis- en gebruikersvelden en het zou vrij snel moeten zijn en u helpen uw gegevens beter te normaliseren.

Ik vind het leuk om de efficiëntie van het afvlakken van een structuur te plotten versus het genormaliseerd te houden als het gaat om de tijd die het me kost om een ​​recordgegevens bij te werken versus het uitlezen van wat ik nodig heb in een query. Je kunt het in grote O-notatie doen, maar je hoeft niet zo luxe te zijn. Zet gewoon wat cijfers op papier op basis van een paar use-cases met verschillende modellen voor de gegevens en krijg een goed gevoel over hoeveel werk er nodig is.

In principe probeer ik eerst de kans te voorspellen hoeveel updates een record zal hebben versus hoe vaak het wordt gelezen. Vervolgens probeer ik te voorspellen wat de kosten van een update zijn versus een uitlezing wanneer deze zowel genormaliseerd als afgevlakt is (of misschien een gedeeltelijke combinatie van de twee die ik kan bedenken … veel optimalisatie-opties). Ik kan dan de besparingen beoordelen om het plat te houden versus de kosten van het opbouwen van de gegevens uit genormaliseerde bronnen. Als ik eenmaal alle variabelen heb uitgezet, als de besparingen om het plat te houden me een hoop bespaart, dan zal ik het plat houden.

Een paar tips:

  • Als je snelle zoekacties nodig hebt om snel en atomair (perfect up-to-date) te zijn, wil je misschien een oplossing waarbij je de voorkeur geeft aan afvlakking boven normalisatie en het nemen van de hit van de update.
  • Als u snel wilt updaten en onmiddellijk toegang wilt hebben, geef dan de voorkeur aan normalisatie.
  • Als u snelle zoekacties nodig hebt, maar geen perfect up-to-date gegevens, overweeg dan om uw genormaliseerde gegevens uit te breiden in batchtaken (mogelijk met behulp van map/reduce).
  • Als uw zoekopdrachten snel moeten zijn en updates zeldzaam zijn en niet noodzakelijkerwijs vereisen dat uw update onmiddellijk toegankelijk is of een vergrendeling op transactieniveau vereist die 100% van de tijd is doorlopen (om te garanderen dat uw update naar schijf is geschreven ), kunt u overwegen uw updates naar een wachtrij te schrijven die ze op de achtergrond verwerkt. (In dit model zul je later waarschijnlijk te maken krijgen met conflictoplossing en verzoening).
  • Profiel verschillende modellen. Bouw een abstractielaag voor gegevensquery’s (zoals een ORM in zekere zin) in uw code, zodat u uw gegevensopslagstructuur later kunt refactoren.

Er zijn veel andere ideeën die u kunt toepassen. Er zijn veel geweldige blogs online die erop ingaan, zoals highscalabilty.org en ervoor zorgen dat je de CAP-stelling begrijpt.

Overweeg ook een caching-laag, zoals Redis of memcache. Ik zal een van die producten voor mijn gegevenslaag plaatsen. Wanneer ik mongo opvraag (die alles genormaliseerd opslaat), gebruik ik de gegevens om een ​​afgeplatte representatie te construeren en op te slaan in de cache. Wanneer ik de gegevens bijwerk, maak ik alle gegevens in de cache ongeldig die verwijzen naar wat ik bijwerk. (Hoewel u de tijd moet nemen die nodig is om gegevens en trackinggegevens in de cache die wordt bijgewerkt, ongeldig te maken, rekening houdend met uw schaalfactoren). Iemand zei ooit: “De twee moeilijkste dingen in de informatica zijn dingen benoemen en het ongeldig maken van de cache.”

Hopelijk helpt dat!


Antwoord 2

Probeer een IList van het type UserEvent-eigenschap toe te voegen aan uw User-object. U hebt niet veel gespecificeerd over hoe uw domeinmodel is ontworpen. Controleer de NoRM-groep http://groups.google.com/group/norm-mongodb/topics
voor voorbeelden.

Other episodes