Software Engineering

Historisierung von Daten mit
Bitemporal Table

In jedem größere Softwareprojekt trifft man auf Daten, welche Abhängigkeiten zu einem Zeitraum haben. Es könnte eine Gültigkeit eines Preisnachlasses sein. Oder eine Dokumentation eines Softwarestandes von einem Steuergerät. Meistens müssen Änderungen dieser Daten dokumentiert werden. Wenn man zudem noch historisieren möchte, zu welchem Zeitpunkt welcher Wert galt, merkt man schnell wie aufwendig so etwas ist.

Es tun sich folgende Fragen auf:

„Welche Zeiträume in der Historie muss ich beim Persistieren mit ändern?“

„Wie stelle ich sicher, dass Zeiträume sich nicht überlappen?“

„Wie implementiere ich die Änderungshistorie für historisierte Zeitabschnitte?“

„Wie baue ich performante Abfragen?“

DB2 von IBM hat für so einen Fall eine Lösung parat. Die Zauberwörter lauten Bitemporal Table. Um zu verstehen, was sich hinter Bitermporal Table verbirgt, müssen wir diesen Ansatz in seine beiden Bestandteile zerlegen.

Anwendung der fachlichen Historisierung

Erstes heißt Application-Period Temporal Table und dient zur fachlichen Historisierung. Hier besitzt jede Zeile in der Datenbanktabelle eine Zeitperiode (BUSINESS_TIME) bestehend aus Start- und Ende-Zeitstempel. Diese Periode wird indexiert, sodass die Suche später recht perfomant funktioniert. Außerdem werden Perioden automatisch von dem Datenbanksystem verwaltet, um Daten einfach lesen und schreiben zu können. Beim Ändern der Zeiträume erstellt das Datenbanksystem automatisch neue Einträge in der Tabelle und passt die Start- und Endzeitpunkte an.

In diesem Beispiel gehen wir davon aus, dass wir eine Datenbanktabelle namens RULE haben.

Dort sind Regeln für eine Rule-Engine hinterlegt. Initial existiert bereits eine Regel in der Tabelle, die seit 04.05.2017 ihre Gültigkeit hat und prüft, ob ein Rabatt auf den Einkauf gibt oder nicht. Laut der Regel 2244 wird ein Rabatt von 10% gegeben, wenn der Betrag höher als 100,- € ist.

Initiale Tabelle: RULE

Nun möchten wir die Höhe des Rabatts ändern und auf 5% reduzieren. Dabei soll die Regel erst ab 01.01.2020 in Kraft treten.

Dadurch dass der Primary Key in der Tabelle aus der ID und der Periode BUSINESS_TIME (valid_from, valid_till) besteht, können Datensätze mit der gleichen ID erstellt werden. In der Abbildung unten ist es erkennbar, dass valid_till beim älteren Datensatz sich automatisch geändert hat, sodass der Endzeitpunkt des älteren Datensatzes der Startzeitpunkt des neuen Datensatzes ist.

Tabelle RULE nach Update

Anzeige der fachlich historisierten Daten

Die Anzeige eines gültigen Datensatz zu einem bestimmten Zeitpunkt erweist sich als sehr einfach. Zu der gesuchten Regel wird einfach eine gesuchte Zeit angegeben. Wie z.B. in der Select-Abfrage unten. Suche mir den aktuell gültigen Stand von der Regel 2244. Statt CURRENT_TIMESTAMP kann man auch ein Datum in der Vergangenheit angeben „2018-08-08 00.00.00.000“.

Ergebnis der Suche

Ohne diese DB-Funktionalität müssten wir ein Update-Statement für die Aktualisierung des älteren Datensatzes und ein Insert-Statement für den neuen Datensatz ausführen. Auch die Abfrage wäre komplexer gewesen, da wir beide Spalten mit den Zeitangaben überprüfen müssten z.B. „CURRENT_TIMESTAMP > valid_from AND CURRENT_TIMESTAMP < valid_till“.

Anwendung der technischen Historisierung

System-Period Temporal Table prädestiniert für das Auditing, enthält ebenso eine Zeitperiode (SYSTEM_TIME). Auch hier übernimmt das System die Verwaltung der Historisierung. Um dies zu ermöglichen, benötigen wir eine zusätzliche Tabelle RULE_HISTORY und zwei Zeitstempel in der Tabelle RULE für die zusätzliche Zeitperiode. In der neuen Tabelle heißen diese Zeitangaben „sys_date_from“ und „sys_date_till“.

Jeder Stand eines geänderten Datensatzes wird in eine separate Tabelle kopiert. Konkret heißt, dass jedes Update und Delete in der Tabelle RULE dazu führt, dass eine Kopie des geänderten Datensatzes in der Tabelle RULE_HISTORY erstellt wird.

Hier führen wir eine Änderungen auf den initialen Stand im ersten Fall aus. Die Aktion von der Regel 2244 wird von „amount * 0,90“ auf „amount * 0,95“ geändert.

Tabelle: RULE

Tabelle: RULE_HISTORY

In der Tabelle RULE ist der aktuellste Stand gepflegt, wohingegen Tabelle RULE_HOSTORY alle älteren Stände umfasst.

Anzeige der technisch historisierten Daten

Filtern von verschiedenen Änderungen aus der DB ist sehr einfach gestaltet. In dem Beispiel unten filtern wir alle Änderungen von 201o bis heute zu der Regel id=2244. Interessant ist, obwohl wir die Abfrage nur auf die Tabelle RULE ausgeführt haben, kommen die historisierten Stände zusätzlich auch von der Tabelle RULE_HISTORY.

Ergebnis der Suche

Bei einer Eigenimplementierung müsste bei so einer Abfrage ein Join auf beide Tabellen ausgeführt werden.

Im Gegensatz zur fachlichen Historisierung, verursachen bei technischer Hostorisierung die Änderungen eines Datensatzes, dass neue Datensätze in der History-Tabelle erzeugt werden. Fachliche Historisierung erstellt neue Datensätze erst bei Änderungen der fachlichen Zeitperiode.

Fazit

Bitemporal Table ist eine sehr nützliche Funktionalität, die einiges vereinfachen kann in der Arbeit mit Zeitperioden. Es erspart viel Code und Logik in der Implementierungsphase. Darüberhinaus bietet dieses Feature wichtige Aspekte für eine qualitativ gute Software, wie Vermeidung von Inkonsistenzen und eine perfomanten Ausführung.

Links

https://www.ibm.com/developerworks/data/library/techarticle/dm-1410temporal-tables-db2zos/