83 Stimmen

Zu viel Datenreplikation in mongodb?

Ich bin neu in diesem ganzen NOSQL-Bereich und bin vor kurzem von mongoDB fasziniert worden. Ich erstelle eine neue Website von Grund auf neu und habe mich entschieden, MONGODB/NORM (für C#) als meine einzige Datenbank zu verwenden. Ich habe viel darüber gelesen, wie man seine Dokumentenmodell-Datenbank richtig gestaltet und denke, dass ich mein Design größtenteils gut ausgearbeitet habe. Ich bin ungefähr 6 Monate in meine neue Website und fange an, Probleme mit Daten-Duplizierung/Synchronisierung zu sehen, mit denen ich immer wieder umgehen muss. Aus dem, was ich gelesen habe, ist das in dem Dokumentenmodell zu erwarten und für die Leistung macht es Sinn. D.h. man fügt eingebettete Objekte in sein Dokument ein, damit es schnell zu lesen ist - keine Joins; aber natürlich kann man nicht immer einbetten, also hat mongodb dieses Konzept einer DbReference, das im Wesentlichen analog zu einem Fremdschlüssel in relationalen Datenbanken ist.

Also hier ist ein Beispiel: Ich habe Benutzer und Veranstaltungen; beide bekommen ihr eigenes Dokument, Benutzer nehmen an Veranstaltungen teil, Veranstaltungen haben Benutzer als Teilnehmer. Ich habe mich entschieden, eine Liste von Veranstaltungen mit begrenzten Daten in die Benutzerobjekte einzubetten. Ich habe auch eine Liste von Benutzern in die Veranstaltungsobjekte als ihre "Teilnehmer" eingebettet. Das Problem hier ist, dass ich jetzt die Benutzer mit der Liste von Benutzern, die auch im Veranstaltungsobjekt eingebettet ist, synchron halten muss. So wie ich es lese, scheint dies der bevorzugte Ansatz zu sein und die NOSQL-Art, Dinge zu tun. Das Abrufen ist schnell, aber der Nachteil ist, wenn ich das Hauptbenutzerdokument aktualisiere, muss ich auch in die Veranstaltungsobjekte gehen, möglicherweise alle Verweise auf diesen Benutzer finden und das ebenfalls aktualisieren.

Die Frage, die ich habe, ist, ob dies ein ziemlich häufiges Problem ist, mit dem die Leute umgehen müssen? Wie oft muss dieses Problem auftreten, bevor man sagt "vielleicht passt die NOSQL-Strategie nicht zu dem, was ich hier versuche zu tun"? Wann verwandelt sich der Leistungsvorteil, keine Joins machen zu müssen, in einen Nachteil, weil es schwierig wird, Daten in eingebetteten Objekten synchron zu halten und mehrere Lesevorgänge in die Datenbank durchzuführen, um dies zu erreichen?

0 Stimmen

Hier ist eine weitere Frage zur Datenredundanz in MongoDB. Meine Antwort dort schlägt vor, das Map-Reduce-Ergebnis als Zwischenspeicher zu verwenden, anstelle einer separaten Zwischenspeicherschicht. Dies kann nützlich sein, wenn Sie mit veralteten Daten leben können. Beachten Sie, dass die Aktualität der Daten davon abhängt, wie oft Sie den Map-Reduce-Job ausführen, z. B. alle 15 Minuten.

0 Stimmen

DBReference ist böse, es nimmt einen Großteil des NoSQL-Charmes weg

0 Stimmen

Es sind bereits zehn Jahre vergangen und diese Frage bleibt weiterhin bestehen :)

72voto

Zac Bowling Punkte 6448

Nun, das ist der Kompromiss bei Dokumentenspeichern. Sie können in einem standardisierten Format wie bei einem herkömmlichen RDMS speichern, und Sie sollten so weit wie möglich nach Normalisierung streben. Nur wenn dies zu Leistungseinbußen führt, sollten Sie die Normalisierung aufbrechen und Ihre Datenstrukturen abflachen. Der Kompromiss liegt zwischen Leseffizienz und Aktualisierungskosten.

Mongo hat wirklich effiziente Indizes, die die Normalisierung erleichtern können wie bei einem traditionellen RDMS (die meisten Dokumentenspeicher bieten dies nicht kostenlos an, deshalb ist Mongo eher eine Hybridlösung als ein reiner Dokumentenspeicher). Damit können Sie eine Beziehungssammlung zwischen Benutzern und Ereignissen herstellen. Dies ist analog zu einer Hilfstabelle in einem tabellarischen Datenspeicher. Indizieren Sie die Felder für Ereignis und Benutzer und es sollte ziemlich schnell gehen und Ihnen helfen, Ihre Daten besser zu normalisieren.

Ich finde es gut, die Effizienz der Verflachung einer Struktur vs. ihrer Beibehaltung normalisiert zu plotten, wenn es darum geht, wie lange es dauert, einen Datensatz zu aktualisieren gegenüber dem Lesen dessen, was ich in einer Abfrage benötige. Sie können dies in Bezug auf die große O-Notation tun, müssen aber nicht so ausgefallen sein. Schreiben Sie einfach einige Zahlen auf Papier, basierend auf einigen Anwendungsfällen mit unterschiedlichen Modellen für die Daten, und entwickeln Sie ein gutes Gespür dafür, wie viel Arbeit erforderlich ist.

Im Grunde genommen versuche ich zuerst vorherzusagen, wie wahrscheinlich es ist, dass ein Datensatz aktualisiert wird im Vergleich dazu, wie oft er gelesen wird. Dann versuche ich vorherzusagen, was die Kosten einer Aktualisierung im Vergleich zu einem Lesevorgang sind, wenn beide normalisiert oder flach sind (oder vielleicht teilweise eine Kombination der beiden, die ich mir vorstellen kann... viele Möglichkeiten zur Optimierung). Ich kann dann die Einsparungen des Verflachens im Vergleich zu den Kosten für den Aufbau der Daten aus normalisierten Quellen beurteilen. Sobald ich alle Variablen geplottet habe, wenn mich das Flachhalten eine Menge spart, werde ich es flach halten.

Ein paar Tipps:

  • Wenn Sie schnell nachschlagen müssen, um sofortige und atomare (perfekt aktuelle) Treffer zu erzielen, sollten Sie eine Lösung bevorzugen, bei der Sie Verflachung über Normalisierung bevorzugen und die Kosten für die Aktualisierung akzeptieren.
  • Wenn Sie möchten, dass Aktualisierungen schnell erfolgen und sofortiger Zugriff möglich ist, bevorzugen Sie Normalisierung.
  • Wenn Sie schnelle Nachschlagevorgänge benötigen, aber nicht unbedingt perfekt aktuelle Daten benötigen, erwägen Sie den Aufbau Ihrer normalisierten Daten in Stapeljobs (möglicherweise unter Verwendung von Map/Reduce).
  • Wenn Ihre Abfragen schnell sein müssen und Aktualisierungen selten sind und nicht unbedingt erfordern, dass Ihre Aktualisierung sofort zugänglich ist oder eine Transaktionsebene erfordern, die 100% der Zeit (um zu gewährleisten, dass Ihre Aktualisierung auf die Festplatte geschrieben wurde) durchliefen, können Sie erwägen, Ihre Aktualisierungen in einer Warteschlange zu schreiben und sie im Hintergrund zu verarbeiten. (In diesem Modell müssen Sie wahrscheinlich später Konfliktlösung und Abgleich behandeln).
  • Profile verschiedene Modelle. Entwickeln Sie eine Datenabfrageabstraktionsschicht (ähnlich einem ORM) in Ihrem Code, damit Sie später Ihre Datenbankspeicherstruktur umgestalten können.

Es gibt viele Ideen, die Sie anwenden können. Es gibt viele großartige Blogs online, die sich damit beschäftigen, wie highscalability.org, und stellen Sie sicher, dass Sie das CAP-Theorem verstehen.

Betrachten Sie auch eine Cache-Schicht wie Redis oder Memcache. Ich werde eines dieser Produkte vor meine Datenschicht setzen. Wenn ich Mongo abfrage (das alles normalisiert speichert), verwende ich die Daten, um eine flache Repräsentation zu erstellen und sie im Cache zu speichern. Wenn ich die Daten aktualisiere, werde ich alle Daten im Cache ungültig machen, die sich auf das beziehen, was ich aktualisiere. (Obwohl Sie die Zeit berücksichtigen müssen, die es dauert, Daten zu invalideren und aktualisierte Daten im Cache zu verfolgen, im Hinblick auf Ihre Skalierungsfaktoren). Jemand hat einmal gesagt: "Die beiden schwierigsten Dinge in der Informatik sind das Benennen von Dingen und die Gültigkeit des Caches."

0 Stimmen

Vielen Dank für die Antwort! Viele gute Einblicke/Ratschläge! Ich habe noch nicht an die Benutzer-Ereignis-Relationssammlung gedacht. Und das Zwischenspeichern wird definitiv etwas sein, worüber ich in Zukunft nachdenken werde.

0 Stimmen

+1 für die Einführung einer Ersatztabelle. Dadurch wird ein einziger Ort geschaffen, an dem die Beziehungen zwischen Dokumenten definiert sind, anstatt zwei. @mike: Ich möchte darauf hinweisen, dass DBRef lediglich eine formale Spezifikation ist, es ist kein Zauber wie Fremdschlüssel :) Referenzen müssen auch manuell gepflegt werden, genauso wie doppelte Daten. Daher würde ich dir nicht raten, 'möglichst nach Normalisierung zu streben'.

0voto

Peter Bromberg Punkte 1506

Versuchen Sie, eine IList-Eigenschaft vom Typ UserEvent zu Ihrem Benutzerobjekt hinzuzufügen. Sie haben nicht viel über das Design Ihres Domänenmodells angegeben. Überprüfen Sie die NoRM-Gruppe http://groups.google.com/group/norm-mongodb/topics für Beispiele.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X