Die gute Performance einer HANA-Datenbank kommt von der konsequenten Orientierung auf eine hauptspeicherbasierte Datenhaltung sowie durch die Nutzung moderner Kompressions- und ColumnStore-Algorithmen. Somit muss die Datenbank bei Aggregationen über große Datenmengen vergleichsweise wenige Daten lesen und kann dies im Hauptspeicher auch noch außerordentlich schnell erledigen.
Jedoch kann bei einem suboptimalen Design des Datenmodells einer dieser Vorteile sehr schnell hinfällig werden. So gehen sowohl der HANA-Datenbank als auch den Anwendern große Vorteile hinsichtlich der Laufzeit und Agilität während der Nutzung verloren.
Der ColumnStore-Index
Eine Ablage der Daten erfolgt in der HANA-Datenbank in zwei Schritten:
Zuerst werden die Daten im Delta Store geschrieben (zeilenbasiert) und dann beim Delta Merge in den Main Store überführt. Dieses Verfahren wird auch von anderen Herstellern angewandt. Ausschlaggebend dafür ist, dass komprimierte ColumnStore-Index-Schreiboperationen nicht direkt erlaubt sind. Denn diese sind einerseits komprimiert und andererseits müssen die Daten "aufwändig" in das spaltenbasierte Format überführt werden.
Der ColumnStore ist insbesondere dann vorteilhaft, wenn wenig Spalten gelesen und viele Zeilen zusammengerechnet werden sollen (bei BI-Anwendungen ist dies im Gegensatz zu ERP-Anwendungsfällen nicht unüblich), und verringert wesentlich die Zugriffe auf das Storage-Medium, da die Daten bereits in Spalten organisiert sind.
Ein klassischer RowStore muss dagegen immer alle betroffenen Zeilen in voller Breite lesen. So entsteht beim Aggregieren ein großer Overhead. Folglich kann festgehalten werden, dass ein ColumnStore-Index für das Zusammenrechnen vieler Daten sehr schnell ist, da die notwendigen Informationen voraggregiert abgelegt sind.
Die HANA Join Engine
Die HANA-Datenbank muss also wenig arbeiten, wenn ich wenige Daten anzeige, aber viele aggregiere. Was passiert jedoch, wenn ich zwei Tabellen über eine granulare Spalte verbinde?
Es ist deutlich zu erkennen, dass die beiden Tabellen auf der Ebene des Join-Kriteriums gelesen werden, bevor eine Aggregation stattfindet. Dies hat zur Folge, dass die HANA-Datenbank viel mehr Daten aus dem Hauptspeicher lesen muss und diese gleichzeitig "on the fly" zu verarbeiten hat. So wird der Vorteil eines ColumnStore durch das Datenmodell zunichtegemacht und die Laufzeit erhöht sich im Vergleich zum persistierten Datamart stark. Bei der Datenmodellierung ist also eine Abwägung zwischen der Flexibilität des Modells und der Performance essentiell.
Ein einfaches Beispiel:
Ein CompositeProvider joint zwei ADSOs mit einerseits Auftragskopf- und andererseits Auftragspositionsdaten, um diese gemeinsam im Reporting zur Verfügung zu stellen. Wir haben 40.000.000 Kopfdaten und 180.000.000 Positionen. Jede Ausführung (und auch Navigation) der Query dauert 5 Sekunden (was in Anbetracht der Datenmenge sehr schnell ist, aber HANA liest ja auch aus dem Hauptspeicher). Persistieren wir nun den Join in einem weiteren ADSO, sodass die Join Engine nicht mehr genutzt wird, zeigt die Query eine Laufzeit von unter 1s. Der Grund ist trivial: Die HANA-Datenbank liest einfach weniger bei gleichem Ergebnis.
Es gibt auch noch weitere Fälle, in denen sich das aufgezeigte Verhalten bemerkbar macht:
Ein Beispiel ist der Distinct Count (Ausnahmeaggregation: Zähler für alle detaillierten Werte, die nicht null sind oder die null sind oder die Fehler enthalten). Die Query liest die SIDs vom InfoObjekt zur Ermittlung der Kennzahl. Dies geschieht über einen Join. Ist das InfoObjekt sehr groß, macht sich das in der Laufzeit der Query bemerkbar, wenn die Kennzahl zur Anzeige kommt. Eine Möglichkeit zur Optimierung ist die Übernahme der SIDs in den DataStore, womit ein Join unterdrückt wird.
Details zu diesem Thema werden in einem späteren Artikel erscheinen, der auf die Optimierung von Distinct-Count-Kennzahlen eingeht.