# Historisierung



## lightme (22. Sep 2010)

Hallo,

im Rahmen meiner Bachelorarbeit muss ich Ansätze entwickeln zur Historisierung von Daten.
Kurz zur Info: Es werden Daten nächtlich überschrieben,... Jedoch möchte man auf die alten Daten auch noch zugreifen können, ohne erheblichen Overhead...
Gibt es vielleicht in der Hinsicht Literempfehlungen?


----------



## Atze (22. Sep 2010)

also ich empfehle 3 liter pils am tag!  ne, schmarn, ich weiß nicht genau was für literatur du suchst, aber ich fänd versionierung (wie es bspw cvs-systeme umsetzten) sinnvoll!

Versionsverwaltung ? Wikipedia


----------



## kama (22. Sep 2010)

Hallo,

wenn Du auf Datenbank Ebene meinst kannst Du dir mal Envers anschauen...

Gruß
Karl Heinz Marbaise


----------



## maki (22. Sep 2010)

Temporal Patterns


----------



## lightme (22. Sep 2010)

also zum technischen Hintergrund:

es ist eine J2EE Webanwendung die, die über eMatrix auf eine DB zugreift...


----------



## lightme (23. Sep 2010)

im Endeffekt ein Produktdatenmanagementsystem.


----------



## Devman (10. Okt 2012)

Hallo zusammen, 

ich beschäftige mich im Moment auch mit dem Thema der Historisierung, jedoch noch auf der Datenmodellierungsebene.

Ohne Literatur schwirren mir zwei Möglichkeiten im Kopf herum:

1. Pro Änderung einen neuen Datensatz in die gleiche Tabelle mit Version, ChangeDate etc. wie es hier schon erwähnt wurde (also Versionierung). 

2. Zu jeder Entity eine Entity_hist Tabelle zu erstellen. Dies würde heißen, dass sobald ein ObjektA geupdatet wird, vor dem Update ein ObjektA_hist in die Historie-tabelle gespeichert wird. Der Vorteil wäre, dass in der ObjektA Tabelle nur aktuelle Objekte vorhanden wären.

Die letzte Idee habe ich noch nicht getestet und es könnte bei 1:N bzw. N:M Beziehungen komplexer werden, da man für jedes dieser Objekten auch einen Eintrag in deren Historie-tabelle machen müsste, jedoch auch die 1. Möglichkeit müsste, um einen historieschen zu erlangen, alle Referenzen nach dem Zeitraum absuchen und die passenden Einträge raussuchen.

Da dies Teil meiner Bachelorarbeit wird, wären Literaturvorschläge von Vorteil, aber wenn jemand Erfahrungen auf dem Gebiet hat, wäre mir dessen Meinung schon hilfreich.

Vielen Dank für eure Zeit!

Devman


----------



## maki (10. Okt 2012)

Vielleciht hilft dir ja das: 
Envers - JBoss Community


----------



## Devman (10. Okt 2012)

Danke für die Antwort, jedoch ist das schon ein Schritt zuweit. Das würde nach meinen Verständnis Möglichkeiten bereitstellen, welche beim Updatevorgang mir Arbeit abnehmen.

Mein Problem ist noch die Datenmodellierung also das Schema der Datenbank. Die Implementierung nachdem ich mich für ein Schema entschieden habe ist nicht so das Problem (aus jetziger Sicht)

Danke im Vorraus.


----------



## Devman (10. Okt 2012)

Devman hat gesagt.:


> Danke für die Antwort, jedoch ist das schon ein Schritt zuweit. Das würde nach meinen Verständnis Möglichkeiten bereitstellen, welche beim Updatevorgang mir Arbeit abnehmen.
> 
> Mein Problem ist noch die Datenmodellierung also das Schema der Datenbank. Die Implementierung nachdem ich mich für ein Schema entschieden habe ist nicht so das Problem (aus jetziger Sicht)
> 
> Danke im Vorraus.



Ergänzung/Doppelpost in meinem Fall: 

Danke nochmal. Ich bin nun über @Audited gestoßen. Nachdem ich das grob überflogen habe, so implementiert dies ähnlich meiner 2. Idee die Historisierung. Werde ich mir nochmal genauer anschauen, bin aber für Alternativen oder Tipps immer noch offen.


----------



## KSG9|sebastian (10. Okt 2012)

Es gibt diverseste Ansätze dafür, alle hängen ein wenig von dem Zugriffen auf die Datenstruktur ab.

- setzt du JPA/ORM ein musst du auch ein Schema verwenden mit dem Hibernate kann
- mit Plain-SQL hast du alle Möglichkeiten

Hab zwei Jahre ein Projekt ausgearbeitet/umgesetzt in dem es genau um Historisierung/temporal/bitemporale Datenhaltung geht. Literatur dazu gibt es relativ wenig.

Folgende Ansätze haben wir verfolgt:

1.) alles in einer Tabelle
Alle Daten werden in einer Tabelle gepflegt (pro Entity). Der PK wird dafür um einen Timestamp erweitert. Wir haben mit Timestamp von und bis gearbeitet. 
Beispiel für ein Entity

```
ID | Timestamp von  | Timestamp bis    | Field 1 | Field 2
1  | 1.1.12 12:00:00 | 2.1.12 13:30:00 | Meier
2  | 2.1.12 13:30:00 | <null>               | Meier
```
Der aktuelle Datensatz wird durch "Timestamp bis" gekennzeichnet. Navigieren zum Satz n+1 bzw n-1 ist sehr einfach da der kommende/vorherige Datensatz über den Timestamp von/bis von Satz n identifiziert werden kann. Die Timestamps müssen immer übereinstimmen, es darf keine Lücke geben.

2.) aktuell und historisiert in zwei Tabellen
selbes Schema wie oben, allerdings wird in der einen Tabelle nur der aktive Satz gepflegt, in der Historientabelle alle Datensätze.
Zugriff auf die aktuellen Sätze ist schneller, dafür ist beim schreiben mehr arbeit notwendig (Satz entfernen, Satz einfügen, Historiensatz einfügen). 

3.) Attribute historisieren
Es werden ID, Timestamp von und bis sowie die Attribute in der Tabelle gepflegt. Geschrieben wird jedoch nur das, was sich ändert. Attribute die sich nicht ändern werden nicht geschrieben.
Insgesamt weniger Daten, dafür sehr aufwändig ein Objekt zusammenzusetzen aus x Datensätzen

Beliebig komplizierter wird das ganze natürlich noch wenn auch fachliche Historisierung/Gültigkeitszeiträume hinzukommen. Dann ist es halt so das zu einem Zeitpunkt mehrere Datensätze technisch gültig sind. Der gültige Satz wird dann über ein zusätzliches fachliches Datum ermittelt.


----------



## Devman (10. Okt 2012)

Danke,

ich denke, dass ich nicht um JPA/Hibernate herum komme, da die Literatur, die JDBC bevorzugt schon was älter ist.

Die ersten beiden Ansätze stimmen mit meinen Ideen überein. Kannst du nach zweijähriger Praxiserfahrung eine Empfehlung aussprechen (Auch in Bezug auf Relationen?)? 

Momentan sieht die Historisierung mit Hibernate sehr interessant aus. Ich werde mal am Wochenende testen, wie flexibel man damit arbeiten kann und wie diese 1:N Beziehungen löst ("zentrale revisionsnummer" fiel da). Zudem die kompatibilität zu JPA testen.

Quelle: Automatische Historisierung mit Hibernate Envers

Ich finde es Schade, dass es dazu wenig Literatur gibt, so wird es schwer in der Bachelorarbeit dies als beste Lösung zu rechtfertigen.


----------



## homer65 (10. Okt 2012)

Wollte auch mal meinen Senf dazu geben.
Bei uns in der Firma werden Daten auch mit unterschiedlichen Methoden langzeit archiviert.
Das funktioniert auch soweit.
Dummerweise mußten wir nun feststellen, das bei alten Daten zwar selbige vorhanden sind, aber es kein Programm mehr existiert, mit dem man sie lesen kann.


----------



## JohannisderKaeufer (12. Okt 2012)

Es stellt sich halt auch immer die Frage ob ein Relationales DB-System die geeignete Wahl ist.

[OT]Hast du schonmal von der Doppelten Buchführung was gehört?

Zu jedem Stichtag wird eine Bilanz erstellt. Dort steht dann was das Unternehmen besitzt und wem es was Schuldet.
Vergleicht man nun zwei Stichtage miteinander kann man daraus den Gewinn ermitteln.

Dann gibt es die Gewinn und Verlustrechnung, bei der aufsummiert wird, was über das Jahr hinweg ausgegeben wurde und eingenommen wurde. Auch hieraus kann man den Gewinn errechnen.
[/OT]

Angenommen ein Dokumentenorientiertes-DB-System würde auf die Daten gut passen.

Dann könntest du Beispielsweise CouchDB nehmen. Dort wird bei jeder Änderung eines Dokuments eine Kopie des alten Dokuments abgelegt. 
Also ein komplettes Abbild des Datensatzes.
Das wäre also wie bei einer Bilanz.


Du könntest aber auch nur die Änderungen erfassen. Also für jede Änderung einen Änderungsdatensatz erstellen.
Oft auch Deltas genannt. Aus diesen Deltas könntest du dann den aktuellen Zustand berechnen.
Das wäre also wie bei der Gewinn und Verlustrechnung.
Letzteres würde man mit einer CouchDB recht einfach, mit dem Reduce (aus Map-Reduce) umsetzen.


Vielleicht sind ja ein paar Anregungen dabei.


----------



## KSG9|sebastian (12. Okt 2012)

Archivierung und Historisierung kann man halt nicht miteinander vergleichen.

Historisierung bzw temporale/bitemporale Datenhaltung wird oftmals eingesetzt wenn die Verarbeitung ältere Daten benötigt.
Bestes Beispiel dafür sind Banken:

Die Monatesende/Jahresendeläufe benötigen nicht den aktuellen Zinssatz sondern die Zinssätze zum Zeitpunkt der zu verarbeitenden Buchung. Auf die (bi)temporalen Datensätze muss online zugegriffen werden können. Da hilft ein Archiv oder eine Kopie des Datensatzes nicht weiter.


Je nach Anforderung gibt es zwei Möglichkeiten für Relationen:

Möglichkeit 1

Die Zugriffslogik muss dann angepasst werden das die Referenz nicht nur über den Schlüssel gebildet wird sondern zusätzlich der Zeitpunkt mitgenommen wird.

Beispiel:


```
ID|Datum|Name
1|1.1-1.5|Maier

Adresse
ID|Datum|ForeignKey
1|1.1-1.3|1

Person_Adresse
PersonId|AdresseId
1|1
```

Zugriffe wären normalerweise ja so:


```
from Person p join fetch p.adresse
```

Diese Logik müsste angepasst werden:

```
from Person p join fetch p.adresse adr where adr.datum > {aktuelles_datum} AND adr.datum <= {aktuelles_datum}
```

Damit verliert man jedoch die Möglichkeiten Referenzen zu ändern. Anforderung kann z.B: sein referenzierte Objekte umzuhängen, z.B. weiße alle Adressen von Person A an Person B zu.

Möglichkeit 2:
Relationen werden in einer Zwischentabelle gepflegt, diese enthält wie bei M-N die jeweiligen Schlüssel des Objekts.
Dadurch muss der Zugriff auf die Relations-Tabelle schon mit einem Timestamp parametrisiert werden


```
ID|Datum|Name
1|1.1-1.5|Maier

Adresse
ID|Datum|ForeignKey
1|1.1-1.3|1

Person_Adresse
PersonId|AdresseId|Datum
1|1|1.1.-1.5
2|1|1.5.-1.9
```

Gibt noch diverse andere Ansätze, allerdings hängen sie sehr stark von den fachlichen Anforderungen ab.

Hibernate Envers ist auch sehr interessant, leider kann es keine bitemporale Datenhaltung out-of-the-box.

Gruß Sebastian


----------



## Devman (12. Okt 2012)

KSG9|sebastian hat gesagt.:


> Hibernate Envers ist auch sehr interessant, leider kann es keine bitemporale Datenhaltung out-of-the-box.



Könntest du das präzesieren bzw. was meinst du mit out-of-the-box?


----------



## Bernd Hohmann (12. Okt 2012)

Devman hat gesagt.:


> Könntest du das präzesieren bzw. was meinst du mit out-of-the-box?



Könntest Du präzisieren was denn überhaupt für Daten "historisiert" werden sollen?

Der simpelste Fall ist die gute alte Kunden/Artikel-Kartei (Welche Artikel hat der Kunde wann zu welchem Preis und Roherlös und Rechnungs/Storno/Gutschriftnummer bekommen bzw. welche Artikel wurden mit welchem Preis etc. an welche Kunden verkaut).

Wenn Deine Daten wirklich "nur" jeden Monat rollierend überschrieben werden, dann schmeisst Du das einfach regelmässig vorher in eine andere DB.

Bernd


----------



## KSG9|sebastian (13. Okt 2012)

Envers kann nur temporale Datenhaltung. Bitemporal geht nur durch Envers anpassen oder ne eigene Schicht darüber welche das für dich löst.


----------

