Bereits im Einstiegspost wurden auf die Vor- aber auch auf die Nachteile von einer NoSQL Datenbank (in meinem Fall RavenDB) eingegangen. Die größte gedankliche Hürde ist das die Datenkonsistenz nicht so einfach sicherzustellen ist, wie in einer klassischen Datenbank.
Ich sprech jetzt mal von RavenDB, weil ich nicht wirklich weiß ob dies bei anderen NoSQL Datenbanken ähnlich ist. Falls ich bei dem geschriebenen auf dem Holzweg bin, sagt mir einfach Bescheid
Wo liegt das Problem?
In einer klassischen Datenbank kann ich Verknüpfungen zwischen Tabelleneinträgen herstellen. Der heilige Gral der Schulweisheit ist eine Datenbank in der 3. Normalform. Beispiel: Ein Kunde macht Bestellungen und kauft dabei ein Produkt.
In Tabellenform gedacht hätten wir nun eine Kunden-Tabelle, eine Produkt-Tabelle und eine Bestellung-Tabelle mit der Referenz zum Kunden und zu einem Produkt. Das Beispiel kann man noch beliebig aufblähen und kennt wahrscheinlich jeder
Es gibt kein Schema…
In RavenDB ist es etwas anders. Dort gibt es keine direkten Verknüpfungen zwischen Dokumenten. Jedes Dokument steht für sich alleine. Siehe auch dieses Bild:
In der RavenDB Doku ist dieser Abschnitt dazu besonders interessant und für Einsteiger empfehlenswert. Natürlich gibt es auch hier “Verbindungen”, allerdings sind diese hier deutlich weicher als in einer klassischen Datenbank. Unter “blogs/9431” gibt es die Verbindung zu dem “users/ayende” Dokument, jedoch lädt RavenDB nicht automatisch irgendwelche Daten nach. Dieses Verhalten kennt man von diversen ORMs, welche über User.Orders.Products.First() witzige SQL Statements erzeugen und die Datenbank unter Last setzt
Hat man dadurch nicht Daten doppelt?
Hier fängt meine “gedankliche Blockade” an - jedoch ist die doppelte Datenhaltung in diesem Fall beabsichtig: Daten sollen doppelt gehalten werden. Wenn wir die Tags und Kategorien an einem Post brauchen um diesen im Frontend darzustellen, dann hängen wir diese Daten da auch mit ran.
(Natürlich kann man solche Sachen auch mit klassischen Datenbanken machen und Daten doppelt vorhalten oder “cachen” – allerdings macht man dies meist aus Performancegründen und nicht weil es so schön elegant ist )
Updateszenarien
Schwierig wird es natürlich nun wenn ich eine Kategorie komplett umbenennen will. In diesem Fall muss man wohl über alle Posts gehen und schauen ob die Kategorie noch dran ist.
An dieser Stelle muss man natürlich entscheiden: Macht es Sinn die Kategorien überall umzubenennen? Wenn wir das Kunde/Bestellsystem Beispiel von oben nehmen: Der Kunde kauft zum Zeitpunkt A ein Produkt namens “Nimbus 2000”. Nun ändere ich zum Zeitpunkt B aber den Namen des Produkt in “Nimbus 2010”. Jetzt sieht es allerdings in der Datenbank so aus als hätte der Kunde den “Nimbus 2010” gekauft. Interessanter wird es noch, wenn ich das Produkt löschen möchte…
Zum Teil macht es auch extrem Sinn die Daten “doppelt” zu halten. Nicht nur von der Performance, sondern auch vom fachlichen.
Was passiert wenn ich ein Feld hinzufüge oder entferne? Wie behalte ich da die Kontrolle?
Diese Frage kam vorhin bei Golo Roden auf. Was passiert, wenn ich nun zu einem Produkt noch zusätzliche Daten abspeichern möchte? Oder ich möchte ein bestimmtes Merkmal nicht mehr speichern? Wie geht RavenDB damit um?
Um es mal einfach zu sagen: RavenDB ist es egal – es serialisiert am Ende nur Objekte als JSON. Alle Daten eines Dokumentes sind als JSON abgespeichert. Da gibt es kein Schema. Wenn ein Property hinzukommt, dann wird es beim Serialisieren berücksichtig. Wenn ich auf “leere” oder “nicht vorhandene” Felder zugreifen möchte bekomme ich in RavenDB einfach ein leeres Objekt zurück. In diesem Fall muss ich mich in der Applikation darum kümmern.
Wenn ein Property entfernt wird, dann wird es im Prinzip auch ignoriert und beim nächsten Speichern wird es auch entfernt – weil das Property nicht mehr vorhanden ist und die alten Daten überschrieben werden.
Schwieriger wird es wenn Properties umbenannt werden, aber auch gibt es ein Extension Point.
Wer vor diesen Problemen steht, sollte nochmal ein Blick auf diesen Blogpost von Ayende werfen:
RavenDB Migrations: Rolling Updates
Auch sehr interessant der Blogpost zu Migrations.
Aller Anfang ist schwer…
Definitiv ist bei NoSQL Datenbanken ein Umdenken erforderlich. So ganz klar und geheuer ist es mir ja noch nicht ganz, aber ich schau immer mal bei der RavenDB Demoapp Raccoon Blog wie der Schöpfer es da gemacht hat