Bitemporale Datenhaltung Der Weg zum unterbrechungsfreien Buchungsschnitt Michael Schöck, Sebastian Komander, AEW6SE | JBFOne 2009
Ziel dieses Vortrags Dieser Vortrag gibt Ihnen einen Überblick über die Konzepte der bitemporalen Datenhaltung Er erläutert die einzelnen Konzepte und Paradigmen der bitemporalen Datenhaltung anhand von Beispielen Er zeigt, wie die FIDUCIA mit diesem Konzept langfristig den unterbrechungsfreien Buchungsschnitt erreichen will
Agenda – Bitemporale Datenhaltung Was ist das? Wozu braucht man das? Wie geht das? Wie nutzt man das?
Agenda – Bitemporale Datenhaltung Was ist das? Wozu braucht man das? Wie geht das? Wie nutzt man das?
Bitemporale Datenhaltung – Was ist das? Unter (bi)temporaler Datenhaltung versteht man das Festhalten der zeitlichen Entwicklung der Daten bei Speicherung in einer Datenbank Häufig reicht es aus, in einer Datenbank nur den jeweils aktuell gültigen Wert zu speichern. Bei einer Änderung wird der alte Wert überschrieben. Wenn jedoch die Forderung besteht, alle Änderungen zu dokumentieren, ist eine (bi)temporale Datenhaltung erforderlich. Diese ermöglicht zu rekonstruieren, welcher Wert zu welchem Zeitpunkt gültig war oder auch gültig werden wird Bei einer bitemporalen Datenhaltung sind zwei Arten der zeitlichen Betrachtung relevant: Transaktionszeit der Zeitpunkt, an dem ein Datenelement im Datenbestand gespeichert wurde Gültigkeitszeit der Zeitraum, in dem ein Datenelement in der realen Welt gültig ist Quelle: wikipedia.de
Agenda – Bitemporale Datenhaltung Was ist das? Wozu braucht man das? Wie geht das? Wie nutzt man das?
Wie der Buchungsschnitt idealtypisch ablaufen müsste? Zwischen 24 und 0 Uhr (logische Sekunde) Standard- Buchungsaufträge Standard-Buchungsaufträge Tagesende-Verarbeitung (Kontenkonzentration und Abrechnung) Tagesanfang- Verarbeitung Bilanz Meldewesen Controlling etc. Abschluss Buchungstag Kein weiterer Umsatz im alten Tag mehr möglich buchen in alten BT buchen in neuen BT Legende: ohne Buchung
Temporale Datenhaltung ist die Voraussetzung für 24*7 Ein fachlicher Datensatz wird nie* gelöscht oder überschrieben Statt dessen werden die Beginn- und Endzeitpunkte seiner Gültigkeit (Transaktionszeitpunkt) im Datensatz selbst gespeichert Eine fachliche Änderung bedeutet, die Gültigkeit des zu ändernden Satzes zu befristen und einen neuen Satz einzufügen, der den Zustand nach Änderung repräsentiert Beispiel: Änderung am 20.7. um 11:40: Familienstand wird von ledig auf verheiratet geändert Zustand vor Änderung Zustand nach Änderung wird neu angelegt Partner (Satz 1) Kenntnis ab: 1.1., 09:10 Unkenntnis ab: unbefristet Familienstand: ledig Partner (Satz 1) Kenntnis ab: 1.1., 09:10 Unkenntnis ab: 20.7., 11:40 Familienstand: ledig Partner (Satz 2) Kenntnis ab: 20.7., 11:40 Unkenntnis ab: unbefristet Familienstand: verheiratet wird befristet * zumindest nicht während der Dauer der Nachweispflicht gemäß GoBS
Soll die fachliche Gültigkeit vom Änderungszeitpunkt entkoppelt werden, benötigt man die Bitemporale Datenhaltung Datensätze enthalten zusätzlich zu den Änderungszeitpunkten einen fachlichen Gültigkeitszeitraum. In diesem Zeitraum sind die Attributwerte des Datensatzes gültig Zu einem Zeitpunkt können damit mehrere technisch gültige Datensätze mit lückenlos aufeinander folgenden fachlichen Gültigkeitszeiträumen existieren Beispiel: Änderung am 20.7., 12:00: Zinssatz wird ab 1.8. von 4% auf 4,5% erhöht Zustand vor Änderung Zustand nach Änderung werden neu angelegt Produkt (Satz 1) Kenntnis ab: 1.1., 00:00 Unkenntnis ab: unbefristet Gültig ab: 1.1. Ungültig ab: unbefristet Zins: 4% Produkt (Satz 1) Kenntnis ab: 1.1., 00:00 Unkenntnis ab: 20.07.,12:00 Gültig ab: 1.1. Ungültig ab: unbefristet Zins: 4% Produkt (Satz 2) Kenntnis ab: 20.7, 12:00 Unkenntnis ab: unbefristet Gültig ab:1.1. Ungültig ab: 1.8. Zins: 4% Produkt (Satz 3) Kenntnis ab: 20.7., 12:00 Unkenntnis ab: unbefristet Gültig ab: 1.8. Ungültig ab: unbefristet Zins: 4,5% wird befristet
Beispiele für Non-/Uni- und Bitemporale Datenhaltung Non-Temporal Aktivität Hinweistext Empfänger Umsatz Betrag Primanota Textschlüssel Zusatztext Temporal Kenntnis ab Unkenntnis ab Kann sein: Kalenderdatum Buchungsdatum Valutadatum Zeitpunkt Natürliche Person Geburtsdatum Geburtsort Bitemporal gültig ab ungültig ab Natürliche Person im Zeitverlauf Familienstand Nachname Anzahl Kinderfreibeträge Kondition Zinssatz
Historisierung von Bestandsdaten im Zielbild Änderung zu beliebigem Zeitpunkt Liefert einfache Sicht auf aktuelle und/oder zukünftige Daten Änderungen erfolgen unabhängig vom Zeitpunkt nach gleichem Muster Anlegen Ändern Löschen Auskunft aktuell und Zukunft Auskunft historisch nach Kriterien Liefert Bestand zu jedem beliebigen Stichzeitpunkt und damit implizit jeden Tagesende-Bestand Änderungen in der Zukunft sind mit Tageswechsel implizit wirksam. Kein Batch notwendig Komponente Ermöglicht die gezielte Recherche auf beliebige Änderungen in der Historie (Temporal) (Bi-) Temporale Entität Entitäten sind in einer homogenen logischen Struktur, unabhängig von ihrem Alter, abgelegt. Alle Daten zu einer Entität liegen (zusammen mit ihrer Geschäftslogik) in einer Komponente Das System ist unterbrechungsfrei DWH wird real time versorgt Die Replikation ist rein technisch. Kein fachliches ETL-Mapping DWH Marts können je nach Anforderung, neartime oder Tages-abgerenzt befüllt werden Legende: (Temporal) Online Batch Marts (Bi-)Temp. Bestand Marts Kompo- nente
Agenda – Bitemporale Datenhaltung Was ist das? Wozu braucht man das? Wie geht das? Wie nutzt man das?
Datenbankdesign – Allgemein Die Zeiten werden im Format JJJJ-MM-TT-hh.mm.ss.mmm (Jahr, Monat, Tag, Stunde, Minute, Sekunde, Millisekunde) gespeichert Bei Entitäten, die z. B. nur tagesgenau gespeichert werden, sind die restlichen Stellen in der Zeit 0 Die OID reicht als Schlüsselfeld nicht aus, da die Objekte bei Änderungen die alte OID beibehalten. Zusätzlich zu der OID müssen weitere Felder in den Primärschlüssel aufgenommen werden
Datenbankdesign – Historisierte Entitäten Historisierte Entitäten werden um die Felder „Kenntnis ab“ sowie „Unkenntnis ab“ erweitert „Kenntnis ab“ ist die Zeit, zu der die Entität gespeichert wurde. Dieses Datum ist auf Millisekunden genau „Unkenntnis ab“ ist die Zeit, zu der die Entität historisiert wurde Das Kenntnis-Intervall ist rechts offen, bedeutet „Kenntnis ab“ inclusive und „Unkenntnis ab“ exclusive Der Primärschlüssel setzt sich aus den Feldern „OID“ und „Kenntnis ab“ zusammen Die aktuell gültige Entität wird durch das „Unkenntnis ab“-Datum 9999-99-99-99.99.99.999 repräsentiert
Datenbankdesign – Historisierte Entitäten OID Kenntnis ab Unkenntnis ab Wert 1 2008-01-01-12.01.31.123 9999-99-99-99.99.99.999 Müller
Datenbankdesign – Historisierte Entitäten OID Kenntnis ab Unkenntnis ab Wert 1 2008-01-01-12.01.31.123 2008-02-01-12.00.23.987 Müller 9999-99-99-99.99.99.999 Meier
Datenbankdesign – Historisierte Entitäten OID Kenntnis ab Unkenntnis ab Wert 1 2008-01-01-12.01.31.123 2008-02-01-12.00.23.987 Müller 2008-03-01-12.42.10.246 Meier 9999-99-99-99.99.99.999 Meier-Müller Historisierte Sätze haben als „Unkenntnis ab“ den „Kenntnis ab“-Wert des folgenden Satzes Der aktuell gültige Satz hat als „Unkenntnis ab“-Wert 9999-99-99-99.99.99.999 Durch die Historie kann einfach navigiert werden mittels Satz n: „Kenntnis ab“ = „Unkenntnis ab“ von Satz n-1 Sätze werden durch ein Update auf das „Unkenntnis ab“-Feld historisiert
Datenbankdesign – Bitemporale Entitäten Bitemporale Entitäten erweitern die historisierten Entitäten um die Felder „Gültig ab“ und „Ungültig ab“ „Gültig ab“ ist die Zeit, zu der die Entität fachlich gültig wird. Die Genauigkeit dieses Datums ist von der Fachlichkeit abhängig. Dieses Datum kann in der Vergangenheit, Gegenwart oder Zukunft liegen „Ungültig ab“ ist die Zeit zu der die Entität fachlich ungültig wird Das Gültigkeits-Intervall ist rechts offen, bedeutet „Gültig ab“ inclusive und „Ungültig ab“ exclusive Der Primärschlüssel setzt sich aus den Feldern „OID“, ,‚Kenntnis ab“ und „Gültig ab“ zusammen Die Entität, die bis auf Weiteres gültig ist, wird mit dem „Ungültig ab“-Datum 9999-99-99-99.99.99.999 gespeichert
Datenbankdesign – Bitemporale Entitäten OID Kenntnis ab Unkenntnis ab Gültig ab Ungültig ab Wert 1 2008-01-01- 12.01.31.123 9999-99-99- 99.99.99.999 2008-01-01- 12.00.00.000 2%
Datenbankdesign – Bitemporale Entitäten OID Kenntnis ab Unkenntnis ab Gültig ab Ungültig ab Wert 1 2008-01-01- 12.01.31.123 2008-02-01- 12.00.23.987 2008-01-01- 12.00.00.000 9999-99-99- 99.99.99.999 2% 2008-05-01- 12.00.00.000 4,5% Bitemporale Sätze haben als „Ungültig ab“ den „Gültig ab“-Wert des folgenden Satzes Durch die Historie kann einfach navigiert werden mittels Satz n: „Gültig ab“ = „Ungültig ab“ von Satz n-1 & „Unkenntnis ab“ = 9999-99-99-99.99.99.999 Sätze werden durch ein Update auf das „Unkenntnis ab“-Feld historisiert und durch ein Update auf das „Ungültig ab“-Feld fachlich ungültig gemacht
Schritt 1 2% OID Kenntnis ab Unkenntnis ab Gültig ab Ungültig ab Wert 1.1.2008 1.1.2008 1.2.2008 1.3.2008 1.4.2008 1.5.2008 1.6.2008 1.7.2008 1.8.2008 1.9.2008 1.10.2008 OID Kenntnis ab Unkenntnis ab Gültig ab Ungültig ab Wert 1 2008-01-01- 12.01.31.123 9999-99-99- 99.99.99.999 2008-01-01- 12.00.00.000 2%
Schritt 2 2% 4,5% 2% OID Kenntnis ab Unkenntnis ab Gültig ab 1.2.2008 2% 1.1.2008 1.1.2008 1.2.2008 1.3.2008 1.4.2008 1.5.2008 1.6.2008 1.7.2008 1.8.2008 1.9.2008 1.10.2008 OID Kenntnis ab Unkenntnis ab Gültig ab Ungültig ab Wert 1 2008-01-01- 12.01.31.123 2008-02-01- 12.00.23.987 2008-01-01- 12.00.00.000 9999-99-99- 99.99.99.999 2% 2008-05-01- 12.00.00.000 4,5%
Agenda – Bitemporale Datenhaltung Was ist das? Wozu braucht man das? Wie geht das? Wie nutzt man das?
Wie nutzt man das? Das Framework für (Bi)temporale Datenhaltung (JPL) basiert auf der Java Persistence API (JPA) – dem Standard für objektrelationales Mapping Die Komplexität der Datenbankoperationen wird vollständig vom Framework übernommen Der Verwender des Frameworks muss sich nicht um komplexe Operationen wie das Aufsplitten und Verschieben von Zeitscheiben kümmern Die Zugriffe auf aktuelle Daten unterscheiden sich nicht von den Zugriffen bei klassischer Datenhaltung Das Framework stellt Funktionen bereit, um auf historisierte Daten sowie auf Daten zuzugreifen, die in der Vergangenheit gültig waren oder in der Zukunft noch gültig werden Das Framework übernimmt Prüfungen, die inkonsistente Datenbestände verhindern Modellierung von bitemporalen Daten werden über den RSA vollständig unterstützt
Wie nutzt man das? the classic way Objekt persistieren DOPerson person = DOPersonHome.getInstance().create(); getPersistenceManager().create(person); Objekt laden String statement = "SELECT p FROM Person p WHERE p.kundenNr=12"; IQuery<DOPerson> query = getPersistenceManager().createQuery(statement, DOPerson.class); DOPerson person = query.getUniqueResult();
Wie nutzt man das? the temporal way Objekt persistieren DOPerson person = DOPersonHome.getInstance().create(); getPersistenceManager().create(person); Objekt laden String statement = "SELECT p FROM Person p WHERE p.kundenNr=12"; IQuery<DOPerson> query = getPersistenceManager().createQuery(statement, DOPerson.class); DOPerson person = query.getUniqueResult();
Wie nutzt man das? the bitemporal way Objekt persistieren DOPerson person = DOPersonHome.getInstance().create(); person.setGueltigAb(TimeUtil.date("1.1.2009")); person.setUngueltigAb(TimeUtil.date("1.5.2009")); getPersistenceManager().create(person); Objekt laden (aktuell gültig) String statement = "SELECT p FROM Person p WHERE p.kundenNr=12"; IQuery<DOPerson> query = getPersistenceManager().createQuery(statement, DOPerson.class); DOPerson person = query.getUniqueResult();
Wie nutzt man das? the bitemporal way Historie anzeigen – was war am 1.3. über die Person bekannt String statement = "SELECT p FROM Person p WHERE p.kundenNr=12"; IQuery<DOPerson> query = getPersistenceManager().createQuery(statement, DOPerson.class, TimeUtil.date("1.3.2009")); DOPerson person = query.getUniqueResult(); Historie anzeigen – welchen Kenntnisstand hatten wir am 1.3.2009 über die Person zum Gültigkeitsdatum 1.10.2010 String statement = "SELECT p FROM Person p WHERE p.kundenNr=12"; IQuery<DOPerson> query = getPersistenceManager().createQuery(statement, DOPerson.class, TimeUtil.date("1.3.2009"), TimeUtil.date("1.10.2010"));
Fragen? – Diskussion? Michael Schöck Anwendungsentwicklung michael.schoeck@fiducia.de Sebastian Komander Anwendungsentwicklung sebastian.komander@fiducia.de
Ihr IT-Partner Vielen Dank