Ich dachte über eine ungewöhnliche Datenbankstruktur nach und fragte mich, ob jemand sie schon einmal gesehen hatte. Grundsätzlich werden 2 Datenbanken verwendet:
- Die erste Datenbank enthält nur die aktuell gültigen Daten
- Die zweite Datenbank enthält den Verlauf aller Daten, die jemals in der ersten Datenbank eingegeben, aktualisiert oder gelöscht wurden
Szenario
Ich arbeite an einem Projekt, in dem ich alles protokollieren muss, was passiert, und in dem sich die Daten häufig ändern.
Beispiel (nicht das echte)
Sie müssen das Datenbankdesign für eine Fußballliga durchführen. In dieser Liga gibt es Spieler und Mannschaften. Die Spieler wechseln oft die Mannschaft.
- Erste Anforderung : Die Datenbank muss die Informationen enthalten, die für das nächste Spiel erforderlich sind. Dies bedeutet eine Liste aller Spieler, Teams und in welchem Team sich jeder Spieler gerade befindet.
- Zweite Anforderung : Die Datenbank muss historische Werte enthalten, anhand derer Statistiken erstellt werden. Dies bedeutet die Liste aller Spieler, die Teil eines Teams waren, oder die Liste aller Teams, zu denen ein Spieler gehört hat.
Das Problem
Diese beiden Anforderungen sind ein bisschen das Gegenteil voneinander. Ich habe versucht, alles in derselben Datenbank zu tun, aber es macht keinen Sinn. Die erste Anforderung befasst sich nur mit dem "Spielen des nächsten Spiels", während sich die zweite Anforderung nur mit dem "Generieren von Statistiken" befasst.
Um alles in derselben Datenbank zu erledigen, habe ich eine Art "Nur einfügen" -Datenbank verwendet, bei der das offensichtliche weiche Löschen zum Löschen / Aktualisieren von Informationen verwendet wurde ...
Was anfangs wie eine leichte Aufgabe schien, eine Liste von Spielern, Teams und dem aktuellen Team jedes Spielers zu führen, wird plötzlich viel schwieriger. Die Anwendungslogik, die zum Spielen des nächsten Spiels erforderlich ist, ist bereits kompliziert genug, aber jetzt hat die Datenbank ein sehr wenig hilfreiches Design, bei dem die Anwendung bei jeder einzelnen Abfrage die Überprüfung "gelöscht" hinzufügen muss , um das nächste Spiel zu spielen.
Möchten Sie der Trainer sein, der "alle Spieler im Team, komm zu mir" schreit und dann 2000 Spieler auf dich zukommen. An diesem Punkt werden Sie wahrscheinlich "alle Spieler , die nicht im Team gelöscht wurden , kommen zu mir" rufen (während Sie über dieses dumme Design schwören).
Meine Schlussfolgerung
Ich habe mich gefragt, warum Sie alles in dieselbe Datenbank stellen müssen. Das weiche Löschen kann nicht nur alles schlecht protokollieren, es sei denn, Sie fügen viele Spalten hinzu (time_created, who_created_it, time_deleted, who_deleted_it), sondern erschwert auch alles. Dies verkompliziert das Datenbankdesign und das Anwendungsdesign.
Außerdem erhalte ich diese beiden Anforderungen als Teil einer einzelnen Anwendung, die nicht aufgeteilt werden kann, aber ich denke immer wieder: Dies sind zwei völlig unterschiedliche Anwendungen. Warum versuche ich alles zusammen zu machen?
Da habe ich darüber nachgedacht, die Datenbank in zwei Teile zu teilen. Eine Betriebsdatenbank, die nur zum Spielen des nächsten Spiels verwendet wird und nur die aktuell gültigen Informationen enthält, und eine historische Datenbank, die alle Informationen enthält, die jemals vorhanden waren, als sie erstellt, gelöscht wurden und wer sie ausgeführt hat.
Ziel ist es, die erste Datenbank (betriebsbereit) und die Anwendung so einfach wie möglich zu halten und gleichzeitig so viele Informationen wie möglich in der zweiten Datenbank (historisch) zu haben.
Fragen
- Haben Sie dieses Design schon einmal gesehen? Hat es einen Namen?
- Gibt es offensichtliche Fallstricke, die mir fehlen?
EDIT 2015-03-16
Aktuelle Architektur
Grundsätzlich können Sie sich die gesamte Architektur in zwei Schritten vorstellen.
Schritt 1 :
- Die Anwendung wird ausgeführt und Benutzer führen einige Aktionen aus
- Jedes Mal, wenn ein Ereignis eintritt, wird es automatisch (Audit-Lösung) in einer Ereignistabelle aufgezeichnet
- Dann wird die richtige Zeile in der Betriebsdatenbank aktualisiert
Schritt 2 :
- Ein Job liest die letzte Einfügung in die Ereignistabelle und fügt diese neuen Daten in die historische Datenbank ein.
- Benutzer fragen die historische Datenbank ab, um die benötigten Informationen abzurufen.
Nur aus der Ereignistabelle können Sie die Informationen zu jedem Zeitpunkt rekonstruieren. Das Problem ist, dass diese Ereignistabelle nicht einfach abfragbar ist. Hier setzt die historische Datenbank an. um die Daten so darzustellen, dass es einfach ist, genau das abzurufen, was wir wollen.
Zusätzliche Probleme, wenn alles in die gleichen Tabellen gestellt wird
Ich habe bereits meine Besorgnis über die zusätzliche Komplexität der Überprüfung "wird gelöscht" bei jeder Abfrage zum Ausdruck gebracht. Aber es gibt noch ein anderes Problem: Integrität .
Ich verwende häufig Fremdschlüssel und Einschränkungen , um sicherzustellen, dass die Daten in meiner Datenbank zu jedem Zeitpunkt gültig sind.
Schauen wir uns ein Beispiel an:
Einschränkung: Es kann nur einen Torhüter pro Team geben.
Es ist einfach, einen eindeutigen Index hinzuzufügen, der überprüft, ob es nur einen Torhüter pro Team gibt. Aber was passiert dann, wenn Sie den Torhüter wechseln? Sie müssen die Informationen über die vorherige noch beibehalten, aber jetzt haben Sie zwei Torhüter in denselben Teams, eine aktive und eine inaktive, was Ihrer Einschränkung widerspricht.
Sicher, es ist einfach, Ihrer Einschränkung einen Scheck hinzuzufügen, aber es ist eine andere Sache, die Sie verwalten und überlegen müssen.