Einer der Punkte in Joshua Blochs Effective Java ist die Vorstellung, dass Klassen die Mutation von Instanzen so wenig wie möglich und vorzugsweise überhaupt nicht zulassen sollten.
Häufig werden die Daten eines Objekts in einer Datenbank in irgendeiner Form gespeichert. Dies hat mich dazu gebracht, über die Idee der Unveränderlichkeit in einer Datenbank nachzudenken, insbesondere für diejenigen Tabellen, die eine einzelne Entität in einem größeren System darstellen.
Mit etwas, mit dem ich in letzter Zeit experimentiert habe, möchte ich versuchen, die Aktualisierungen zu minimieren, die ich an Tabellenzeilen vornehme, die diese Objekte darstellen, und stattdessen so viel wie möglich Einfügungen durchführen.
Ein konkretes Beispiel für etwas, mit dem ich kürzlich experimentiert habe. Wenn ich weiß, dass ich später möglicherweise einen Datensatz mit zusätzlichen Daten anhängen werde, erstelle ich eine weitere Tabelle, um dies darzustellen. Diese entspricht etwa den beiden folgenden Tabellendefinitionen:
create table myObj (id integer, ...other_data... not null);
create table myObjSuppliment (id integer, myObjId integer, ...more_data... not null);
Es ist hoffentlich klar, dass diese Namen nicht wörtlich sind, sondern nur, um die Idee zu demonstrieren.
Ist dies ein vernünftiger Ansatz für die Datenpersistenzmodellierung? Lohnt es sich, Aktualisierungen für eine Tabelle einzuschränken, insbesondere um Nullen für Daten einzufügen, die möglicherweise nicht vorhanden sind, als der Datensatz ursprünglich erstellt wurde? Gibt es Zeiten, in denen ein solcher Ansatz später starke Schmerzen verursachen könnte?
quelle
UPDATE
). Wie die Krankenakten des Arztes.Antworten:
Der Hauptzweck der Unveränderlichkeit besteht darin, sicherzustellen, dass sich die Daten im Speicher zu keinem Zeitpunkt in einem ungültigen Zustand befinden. (Der andere Grund ist, dass mathematische Notationen zumeist statisch sind und daher unveränderliche Dinge einfacher zu konzipieren und mathematisch zu modellieren sind.) Wenn ein anderer Thread versucht, Daten zu lesen oder zu schreiben, während er bearbeitet wird, wird er möglicherweise beschädigt oder es könnte sich in einem korrupten Zustand befinden. Wenn Sie in einer Multithread-Anwendung mehrere Zuweisungsvorgänge zu den Feldern eines Objekts ausführen, versucht möglicherweise ein anderer Thread, dazwischen damit zu arbeiten - was möglicherweise schlecht ist.
Die Unveränderlichkeit behebt dies, indem zuerst alle Änderungen an eine neue Stelle im Speicher geschrieben werden und dann die endgültige Zuweisung als ein Schritt ausgeführt wird, bei dem der Zeiger auf das Objekt neu geschrieben wird, um auf das neue Objekt zu verweisen - was auf allen CPUs ein Atom ist Operation.
Datenbanken machen dasselbe mit atomaren Transaktionen : Wenn Sie eine Transaktion starten, schreibt sie alle neuen Aktualisierungen an einen neuen Ort auf der Festplatte. Wenn Sie die Transaktion abschließen, ändert sich der Zeiger auf der Festplatte an die Stelle, an der sich die neuen Aktualisierungen befinden. Dies geschieht in einem kurzen Moment, in dem andere Prozesse ihn nicht berühren können.
Dies ist auch genau das Gleiche wie Ihre Idee, neue Tabellen zu erstellen, mit der Ausnahme, dass dies automatischer und flexibler ist.
Zur Beantwortung Ihrer Frage: Ja, Unveränderlichkeit ist in Datenbanken gut, aber nein, Sie müssen nur zu diesem Zweck keine separaten Tabellen erstellen. Sie können einfach alle atomaren Transaktionsbefehle verwenden, die für Ihr Datenbanksystem verfügbar sind.
quelle
Dies hängt davon ab, welchen Nutzen Sie von der Unveränderlichkeit erwarten. Rei Miyasakas Antwort sprach einen an (Vermeidung ungültiger Zwischenzustände), aber hier ist ein anderer.
Mutation wird manchmal als destruktives Update bezeichnet : Wenn Sie ein Objekt mutieren, geht der alte Zustand verloren (es sei denn, Sie ergreifen zusätzliche Schritte, um es explizit zu erhalten). Im Gegensatz dazu ist es bei unveränderlichen Daten trivial, den Zustand vor und nach einer Operation gleichzeitig darzustellen oder mehrere Nachfolgezustände darzustellen. Stellen Sie sich vor, Sie möchten eine Breitensuche durch Mutieren eines einzelnen Statusobjekts implementieren.
Dies wird wahrscheinlich in der Datenbankwelt am häufigsten als zeitliche Daten angezeigt . Sagen wir letzten Monat, Sie waren im Basisplan, aber am 16. haben Sie zum Premiumplan gewechselt. Wenn wir nur ein Feld überschrieben, das angibt, auf welchem Plan Sie sich befinden, können wir Probleme haben, die richtige Abrechnung zu erhalten. Es könnte uns auch die Möglichkeit fehlen, Trends zu analysieren. (Hey, schau, was diese lokale Werbekampagne gemacht hat!)
Das ist es, woran ich denke, wenn Sie "Unveränderlichkeit im Datenbankdesign" sagen.
quelle
Customer
Tabellenfelder, nur um sich daran zu erinnern, dass der Benutzer den Plan geändert hat, bringt nichts als einen großen Leistungsnachteil, langsamere Auswahl über die Zeit, komplizierteres Data Mining (im Vergleich zu Protokollen) und mehr verschwendeten Speicherplatz.Wenn Sie an den Vorteilen interessiert sind, die sich aus der Unveränderlichkeit in einer Datenbank ergeben, oder zumindest an einer Datenbank, die die Illusion von Unveränderlichkeit bietet, aktivieren Sie Datomic.
Datomic ist eine Datenbank, die von Rich Hickey in Zusammenarbeit mit Think Meaning entwickelt wurde. In zahlreichen Videos werden die Architektur, die Ziele und das Datenmodell erläutert. Suchen Sie nach infoq, eine davon trägt den Titel Datomic, Database as a Value . In Confreaks finden Sie eine Keynote, die Rich Hickey auf der Euroclojure-Konferenz im Jahr 2012 hielt
Unter vimeo.com/53162418 gibt es einen Vortrag, der eher entwicklungsorientiert ist.
Hier ist eine weitere von Stuart Halloway unter .pscdn.net/008/00102/videoplatform/kv/121105techconf_close.html
Nun, da die Informationen als Fakten in der Zeit gespeichert sind:
Die Datenbank ist ein Wert und ein Parameter für die Abfrage-Engine. Die QE verwaltet die Verbindung und das Caching. Da Sie die Datenbank als Wert und unveränderliche Datenstruktur im Speicher sehen können, können Sie sie mit einer anderen Datenstruktur aus Werten "in der Zukunft" zusammenführen und diese mit zukünftigen Werten an die QE & Query übergeben, ohne die tatsächliche Datenbank zu ändern .
Es gibt ein Open-Source-Projekt von Rich Hickey mit dem Namen codeq . Sie finden es in github Datomic / codeq, das das Git-Modell erweitert, Verweise auf Git-Objekte in einer datenbankfreien Datenbank speichert und Abfragen Ihres Codes vornimmt Hier sehen Sie ein Beispiel für die Verwendung von Datomic.
Sie können sich datomic als ACID NoSQL vorstellen. Mit Datumsangaben können Sie Tabellen oder Dokumente oder Kv-Speicher oder Diagramme modellieren.
quelle
Die Idee, Aktualisierungen zu vermeiden und Einfügungen zu bevorzugen, ist einer der Gründe für den Aufbau Ihres Datenspeichers als Ereignisquelle. Diese Idee wird häufig zusammen mit CQRS verwendet. In einem Ereignisquellenmodell gibt es keine Aktualisierung: Ein Aggregat wird als Sequenz seiner "Transformation" (Ereignisse) dargestellt, und der Speicher ist daher nur anhängbar.
Diese Seite enthält interessante Diskussionen zu CQRS und Event Sourcing, wenn Sie neugierig sind!
quelle
Dies steht in enger Beziehung zu den sogenannten "sich langsam ändernden Dimensionen" in der Data-Warehousing-Welt und zu den "zeitlichen" oder "bi-zeitlichen" Tabellen in anderen Domänen.
Das Grundkonstrukt ist:
Der Vorteil dieses Schemas besteht darin, dass Sie den "Status" Ihrer logischen Entität zu jedem Zeitpunkt neu erstellen können, über einen längeren Zeitraum einen Verlauf Ihrer Entität haben und Konflikte minimieren können, wenn Ihre "logische Entität" stark ausgelastet ist.
Die Nachteile sind, dass Sie viel mehr Daten speichern und mehr Indizes verwalten müssen (zumindest bei Logical Key + ValidFrom + ValidTo). Ein Index für Logical Key + Latest Version beschleunigt die meisten Abfragen erheblich. Es erschwert auch Ihre SQL!
Es liegt an Ihnen, ob dies sinnvoll ist, es sei denn, Sie müssen wirklich einen Verlauf führen und den Status Ihrer Entitäten zu einem bestimmten Zeitpunkt neu erstellen.
quelle
Ein weiterer möglicher Grund für eine unveränderliche Datenbank wäre die Unterstützung einer besseren Parallelverarbeitung. Aktualisierungen, die nicht in der richtigen Reihenfolge durchgeführt werden, können die Daten permanent durcheinander bringen. Daher muss eine Sperrung erfolgen, um dies zu verhindern und die parallele Leistung zu beeinträchtigen. Viele Einfügungen von Ereignissen können in beliebiger Reihenfolge erfolgen, und der Zustand wird zumindest irgendwann richtig sein , solange alle Ereignisse irgendwann verarbeitet werden. Dies ist jedoch so hart zu arbeiten mit in der Praxis im Vergleich zu Datenbank - Updates zu tun , dass Sie wirklich viel Parallelität berücksichtigen müssen , die Dinge so zu tun haben würden - ich bin nicht es zu empfehlen.
quelle
Haftungsausschluss: Ich bin so ziemlich neu in DB: p
Davon abgesehen hat dieser Ansatz der Satellitendarstellung einen unmittelbaren Einfluss auf die Leistung:
Abhängig von Ihren Anforderungen können Sie dies entweder begrüßen oder nicht, aber es ist sicherlich ein Punkt, den Sie berücksichtigen sollten.
quelle
Ich verstehe nicht, wie Ihr Schema "unveränderlich" genannt werden kann.
Was passiert, wenn sich ein in der Ergänzungstabelle gespeicherter Wert ändert? Es sieht so aus, als müssten Sie eine Aktualisierung für diese Tabelle durchführen.
Damit eine Datenbank wirklich unveränderlich ist, muss sie ausschließlich von "INSERTS" verwaltet werden. Dazu benötigen Sie eine Methode zur Identifizierung der "aktuellen" Zeile. Dies führt fast immer zu einer schrecklichen Ineffizienz. Sie müssen entweder alle vorherigen unveränderten Werte kopieren oder den aktuellen Status aus mehreren Datensätzen zusammenfügen, wenn Sie eine Abfrage durchführen. Die Auswahl der aktuellen Zeile erfordert normalerweise etwas schrecklich chaotisches SQL wie (
where updTime = (SELECT max(updTime) from myTab where id = ?
).Dieses Problem tritt häufig in DataWarehousing auf, wo Sie einen Verlauf der Daten über einen bestimmten Zeitraum hinweg führen und den Status für einen bestimmten Zeitpunkt auswählen müssen. Die Lösung sind normalerweise "dimensionale" Tabellen. Während sie jedoch das DW-Problem "Wer war der Vertriebsmitarbeiter im letzten Januar" lösen. Sie bieten keinen der Vorteile, die unveränderliche Klassen von Java bieten.
Auf einer philosophischeren Anmerkung; Es gibt Datenbanken, in denen der Status gespeichert wird (Ihr Kontostand, Ihr Stromverbrauch, Ihre Brownie-Punkte für StackOverflow usw. usw.). Der Versuch, eine "zustandslose" Datenbank zu erstellen, scheint eine ziemlich sinnlose Aufgabe zu sein.
quelle
WHERE id = {} ORDER BY updTime DESC LIMIT 1
Allgemeinen nicht zu ineffizient.