2010-11-08 16 views
84

Ich versuche herauszufinden, das Äquivalent von Fremdschlüsseln und Indizes in NoSQL KVP oder Document-Datenbanken. Da es keine zentralen Tabellen gibt (um Schlüssel hinzuzufügen, die eine Beziehung zwischen zwei Objekten markieren), bin ich wirklich verwirrt darüber, wie Sie Daten auf eine Weise abrufen könnten, die für normale Webseiten nützlich wäre.Wie verfolgen Sie die Datensatzbeziehungen in NoSQL?

Angenommen, ich habe einen Benutzer, und dieser Benutzer hinterlässt viele Kommentare auf der Website. Der einzige Weg, ich denken kann verfolgen, dass die Nutzer Kommentare zu halten, ist zu

  1. einbetten sie in dem Benutzerobjekt (die ziemlich nutzlos scheint)
  2. einen user_id:comments Wert erstellen und pflegen, die eine Liste von jedem Kommentar des enthält Schlüssel [Kommentar: 34, Kommentar: 197, etc ...] so dass ich sie nach Bedarf abrufen kann.

jedoch das zweite Beispiel verwenden, können Sie treffen bald eine Mauer, wenn Sie es für die Verfolgung von anderen Dingen wie ein Schlüssel verwenden „active_comments“, die 30 Millionen-IDs darin enthalten könnte so dass es eine Tonne kosten zu Fragen Sie jede Seite ab, nur um einige kürzlich aktive Kommentare zu erhalten. Es wäre auch sehr anfällig für Race-Bedingungen so viele Seiten könnten versuchen, es zur gleichen Zeit zu aktualisieren.

Wie kann ich Beziehungen wie die folgenden in einer NoSQL-Datenbank verfolgen?

  • Alle eines Benutzers Kommentare
  • Alle aktiven Kommentare
  • Alle Beiträge mit [Keyword] getaggt
  • alle Schüler in einem Club - oder alle Clubs ein Student in
  • ist

Oder denke ich falsch darüber nach?

+0

Es gibt keine Möglichkeit, dies in NoSQL-Datenbanken zu tun, diese Frage ist eher eine Frage zu stellen, wie würde ich Beziehungen in C-Programmen verfolgen. – stonemetal

+3

Wow, dann denke ich, dass der Hype um NoSQL, der RDBMS ersetzt, unmöglich ist. – Xeoncross

+10

Ja, NoSQL ist definitiv übersteuert. Ich sage nicht, dass die neuen Technologien unter den richtigen Umständen nicht nützlich sind, aber es ist lächerlich zu denken, dass sie das RDBMS ersetzen werden. Siehe http://en.wikipedia.org/wiki/Hype_cycle –

Antwort

124

Alle Antworten für wie viele-zu-viele Vereine in der „NoSQL Art und Weise“ speichern, um die gleiche Sache reduzieren: Speicherung redundant Daten.

In NoSQL entwerfen Sie Ihre Datenbank nicht basierend auf den Beziehungen zwischen Datenentitäten. Sie entwerfen Ihre Datenbank basierend auf den Abfragen, die Sie dagegen ausführen. Verwenden Sie dieselben Kriterien, die Sie zum Denormalisieren einer relationalen Datenbank verwenden würden: Wenn es wichtiger ist, dass Daten kohäsiv sind (denken Sie an Werte in einer durch Kommas getrennten Liste anstelle einer normalisierten Tabelle), dann tun Sie es so.

Aber dies optimiert zwangsläufig für eine Art von Abfrage (z. B. Kommentare von jedem Benutzer für einen bestimmten Artikel) auf Kosten von anderen Arten von Abfragen (Kommentare für einen Artikel von einem bestimmten Benutzer). Wenn Ihre Anwendung beide Arten von Abfragen gleichermaßen optimieren muss, sollten Sie nicht denormalisieren. Außerdem sollten Sie keine NoSQL-Lösung verwenden, wenn Sie die Daten relational verwenden müssen.

Es besteht ein Risiko bei der Denormalisierung und Redundanz, dass redundante Datensätze nicht mehr synchron zueinander sind. Dies nennt man eine Anomalie. Wenn Sie eine normalisierte relationale Datenbank verwenden, kann das RDBMS Anomalien verhindern. In einer denormalisierten Datenbank oder in NoSQL liegt es in Ihrer Verantwortung, Anwendungscode zu schreiben, um Anomalien zu vermeiden.

Man könnte denken, dass es für eine NoSQL-Datenbank toll wäre, die harte Arbeit zu tun, um Anomalien für Sie zu verhindern. Es gibt ein Paradigma, das dies tun kann - das relationale Paradigma.

+11

"Sie sollten keine NoSQL-Lösung verwenden, wenn Sie die Daten auf eine relationale Weise verwenden müssen" - Wie also kommen andere, die NoSQL ausführen, damit davon? Wie können Sie möglicherweise alle Methoden kennen, mit denen Sie Daten abfragen, wenn Sie Ihre Anwendung zum ersten Mal entwerfen? Fox Beispiel, ich möchte vielleicht aktuelle Kommentare, Kommentare von Benutzern, Kommentare nach Tag, Kommentare für einen bestimmten Beitrag, Kommentare als Spam markiert, aktive Kommentare, am höchsten bewertete Kommentare usw. – Xeoncross

+7

Genau - es gibt nicht so etwas wie " es funktioniert einfach ", wie die Befürworter von NoSQL gerne behaupten. Entweder machen Sie eine Reihe von Analysen im Vorfeld für Ihre relationale Datenmodellierung, oder Sie machen eine Reihe von Analysen für Ihre Top-Prioritätsabfragen, oder Sie führen eine Reihe von kostspieligen Refactoring während des Projekts, wenn Sie entdecken, welche Teile Ihres Designs hat im Vorfeld nicht genug Analysen bekommen. –

+0

@Xeoncross Ich verstehe auch dieses Problem. Sehen Sie sich Sekundärindizes an. Im Allgemeinen erstellt NoSQL sekundäre Indizes, um verschiedene Anwendungsfälle zu erfüllen. Allerdings wird eine geringere Anzahl von Sekundärindizes bevorzugt. –

4
  1. Benutzer: Benutzer-ID: Kommentare ist ein vernünftiger Ansatz - man denke an sie als Äquivalent eines Spaltenindex in SQL, mit dem zusätzlichen Anforderung, dass Sie nicht auf Spalten ohne Index abfragen.

  2. Hier müssen Sie über Ihre Anforderungen nachdenken. Eine Liste mit 30 Millionen Artikeln ist nicht unvernünftig, weil sie langsam ist, aber weil es unpraktisch ist, irgendetwas damit zu tun. Wenn Sie aktuelle Kommentare anzeigen möchten, sollten Sie eine sehr kurze Liste erstellen, die bei jedem Kommentar aktualisiert wird. Denken Sie daran, dass NoSQL keine Normalisierungsanforderungen hat. Race-Bedingungen sind ein Problem mit Listen in einem grundlegenden Schlüsselwertspeicher, aber im Allgemeinen unterstützt entweder Ihre Plattform Listen ordnungsgemäß, Sie können etwas mit Sperren tun, oder Sie interessieren sich nicht wirklich für fehlgeschlagene Updates.

  3. Gleiche wie für Benutzer Kommentare - einen Index Schlüsselwort erstellen: Beiträge

  4. More of the same - wahrscheinlich eine Liste von Clubs als Eigenschaft von Studenten und ein Index auf diesem Gebiet alle Mitglieder eines Clubs zu bekommen

+0

Also, im Grunde braucht alles nur Listen? Es scheint, dass es einen ausgefeilteren Ansatz geben sollte, als nur manuell die Strings von IDs zu verfolgen. Zum einen können Sie nur so weit gehen, bevor sie zu groß werden, um nützlich zu sein. Andererseits sind die wichtigsten Poster-Child-Projekte der NoSQL-Technologie (MongoDB, CouchDB, Membase usw.) alle neue Projekte, also muss ich ihnen vielleicht mehr Zeit geben, um eine bessere Möglichkeit zum Nachverfolgen von Beziehungen zu finden. – Xeoncross

+0

Wenn Sie NoSQL (nicht-relationale ALA-Datenspeicher) verwenden, müssen Sie aufhören, in relationalen Begriffen zu denken. Der verwendete Ansatz unterscheidet sich je nach Plattform, aber die Grundidee, Indizes zu verwalten, ist ziemlich universell. Die von Ihnen angegebenen Beziehungsbeispiele werden in NoSQL auf zwei verschiedene Arten modelliert: 1) Speicher - im Gegensatz zu SQL können Spalten mehrere/komplexe Werte haben, sodass das untergeordnete Objekt nur ein Teil des übergeordneten Objekts ist. 2) Suche - Ihre langen Listen sind eigentlich eine Voraussetzung für die Durchsuchbarkeit, das bedeutet Indexierung - Sie könnten eine einfache benutzerdefinierte Liste oder eine vollständigere Suchmaschine verwenden. –

3

der CouchDB Ansatz vorschlagen richtige Klassen von Sachen in der Karte Phase zu emittieren und fasst es .. in reduzieren, damit Sie alle Kommentaren und 1 für den jeweiligen Benutzer emittieren Karte könnten und später einzige ausdrucken.Es würde jedoch viel Festplattenspeicher benötigen, um dauerhafte Ansichten aller verfolgbaren Daten in CouchDB zu erstellen. Übrigens haben sie auch diese Wiki-Seite über Beziehungen: http://wiki.apache.org/couchdb/EntityRelationship.

Riak auf der anderen Seite hat ein Werkzeug, um Beziehungen aufzubauen. Es ist ein Link. Sie können die Adresse eines verknüpften Dokuments (hier Kommentar) in das Stammdokument (hier Benutzerdokument) eingeben. Es hat einen Trick. Wenn es verteilt wird, kann es an vielen Stellen gleichzeitig modifiziert werden. Es wird zu Konflikten und als Folge zu großen Vektor-Uhr-Baum:/..nicht so schlecht, nicht so gut.

Riak hat noch einen weiteren "Mechanismus". Es hat 2-Layer-Schlüsselnamensraum, so genannte Eimer und Schlüssel. Also, für Schüler Beispiel Wenn wir Club A, B und C und Schüler StudentX, studenty könnten Sie folgende Konvention halten:

{ Key = {ClubA, StudentX}, Value = true }, 
{ Key = {ClubB, StudentX}, Value = true }, 
{ Key = {ClubA, StudentY}, Value = true } 

und Beziehung nur Liste Tasten in bestimmten Eimer zu lesen. Was stimmt damit nicht? Es ist verdammt langsam. Die Auflistung von Buckets war für Riak nie vorrangig. Es wird immer besser und besser. übrigens. Sie verschwenden keinen Speicher, weil dieses Beispiel {true} mit einem einzigen vollen Profil von StudentX oder Y verknüpft werden kann (hier sind Konflikte nicht möglich).

Wie Sie sehen NoSQL! = NoSQL. Sie müssen sich die spezifische Implementierung ansehen und sie selbst testen.

Erwähnt vor Spaltenspeichern aussehen wie gut passen für Beziehungen .. aber es hängt alles von Ihren A und C und P Bedürfnisse;) Wenn Sie nicht brauchen A und Sie haben weniger als Peta Bytes lassen Sie es einfach, weiter mit MySql oder Postgres.

Glück

+1

Riak hat vor kurzem die Version 1.0 veröffentlicht, die Unterstützung für sekundäre Indizes bietet, wenn das LevelDB-Backend verwendet wird. Sehr wertvolle Eigenschaft. –

0

Ich denke RavenDB bietet eine gute Lösung für dieses Problem mit Indexierung. Die Informationen auf der Hauptseite http://ravendb.net/ erklärt das Konzept gut genug, dass Sie wahrscheinlich etwas Analoges für Ihre Technologie erstellen könnten.

1

Sie haben

"user": { 
    "userid": "unique value", 
    "category": "student", 
    "metainfo": "yada yada yada", 
    "clubs": ["archery", "kendo"] 
} 

"comments": { 
    "commentid": "unique value", 
    "pageid": "unique value", 
    "post-time": "ISO Date", 
    "userid": "OP id -> THIS IS IMPORTANT" 
} 

"page": { 
    "pageid": "unique value", 
    "post-time": "ISO Date", 
    "op-id": "user id", 
    "tag": ["abc", "zxcv", "qwer"] 
} 

Well in einer relationalen Datenbank, um die normale Sache in einer Beziehung einer Eins-zu-viele-zu tun wäre, um die Daten zu normalisieren. Das ist dasselbe, was Sie auch in einer NoSQL-Datenbank tun würden. Indexieren Sie einfach die Felder, mit denen Sie die Informationen abrufen möchten.

Zum Beispiel die wichtigen Indizes für Sie sind

  • Comment.UserID
  • Comment.PageID
  • Comment.PostTime
  • Page.Tag []

Wenn Sie verwenden NosDB (A .NET based NoSQL Database with SQL support) Ihre Abfragen werden wie

sein
SELECT * FROM Comments WHERE userid = ‘That user’; 

SELECT * FROM Comments WHERE pageid = ‘That user’; 

SELECT * FROM Comments WHERE post-time > DateTime('2016, 1, 1'); 

SELECT * FROM Page WHERE tag = 'kendo' 

Überprüfen Sie alle unterstützten Abfragetypen von ihrer SQL cheat sheet oder Dokumentation.

Verwandte Themen