Lange Antwortzeiten bei grossen Datamarts (Teil 2) - Trivadis
Lange Antwortzeiten bei grossen Datamarts (Teil 2) - Trivadis
Lange Antwortzeiten bei grossen Datamarts (Teil 2) - Trivadis
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
Betrifft <strong>Lange</strong> <strong>Antwortzeiten</strong> <strong>bei</strong> <strong>grossen</strong> <strong>Datamarts</strong>? Dies muss nicht so sein!<br />
Art der Info Methodische Background Info (<strong>Teil</strong>2)<br />
Autor Karol Hajdu, <strong>Trivadis</strong> AG<br />
Quelle Aus unserer Schulungs- und Beratungstätigkeit<br />
Einleitung<br />
<strong>Datamarts</strong> sind spezialisierte, auf Performance und Ergonomie optimierte Datenstrukturen, welche als<br />
Abfragequelle für eine breite Skala von Auswertungsbedürfnissen der Endbenutzer verwendet werden.<br />
Die <strong>Datamarts</strong> kann man als „Schaufenster“ eines Data Warehouses bezeichnen.<br />
In dieser Artikelserie erfahren Sie einerseits, wo die Fallstricke <strong>bei</strong>m Design der <strong>Datamarts</strong> liegen, und<br />
andererseits auch die Methodik, um Designprobleme, welche zu schlechter Abfragenperformance<br />
führen, zu vermeiden.<br />
Die Erläuterungen werden sich an Beispielen aus der Praxis anlehnen.<br />
Das Vorgehen der Methodik unterscheidet folgende drei Hauptphasen:<br />
- dimensionale Modellierung (technologie-unabhängiges Modell)<br />
- relationales Design (Umsetzung des dimensionalen Modells ins relationale Schema)<br />
- physisches Design der DB-Objekte (erzielt die gleichmässige Lastverteilung auf HW-<br />
Ressourcen)<br />
In diesem Artikel finden Sie eine Untermenge der gesamten Designmethodik: nämlich die, welche<br />
unmittelbar mit der Performance der Abfragen zusammenhängt. Ausführliche Erklärungen zur ganzen<br />
Methodik (Ergonomie, Zugriffschutz etc.) werden am ersten Tag unseres Standard-Kurses „Data<br />
Warehousing mit Oracle“ vermittelt.<br />
Nach dem wir uns im vorherigen Artikel der Phase dimensionale Modellierung gewidmet haben, liegt<br />
der Schwerpunkt vom diesen Artikel im relationalen Design.<br />
Problemstellung<br />
Bekanntlich ist ein relationales Schema durch Tabellen und Beziehungen gebildet. Die Umsetzung<br />
eines dimensionalen Modells (Dimensionen und Kennzahlen) läuft somit auf ein sog. Star-Schema<br />
hinaus (Fakttabelle mit Kennzahlen in der Mitte, verknüpft mit Dimensionstabellen).<br />
Das Design dieser Strukturen hat folgende Zielsetzungen:<br />
a) Verbindung zwischen Kennzahlen und Dimensionsmembers so zu gestalten, dass fürs<br />
Herausfinden der oft abgefragten Beziehungen möglichst wenig I/O, Memory & CPU<br />
notwendig ist<br />
1/12
) <strong>bei</strong>m Aktualisieren der Kennzahlen und Dimensionsmembers (neue Fakten zugekommen,<br />
Eigenschaften der Members haben sich geändert) muss nur ein Minimum der gespeicherten<br />
Daten 1 modifiziert werden<br />
c) die zugrunde liegenden atomaren Daten sollen in solcher Form gespeichert werden, welche<br />
ein einfaches, automatisierbares Anlegen von Indexen und gespeicherten Aggregaten 2<br />
erlaubt<br />
... und wo liegt das Problem?<br />
Wie <strong>bei</strong>m täglichen Leben so üblich – <strong>bei</strong> der Umsetzung :-):<br />
Wie gehe ich konkret vor, damit ich die vorher formulierte Zielsetzung erreiche?<br />
... leider existiert immer noch - besonders auf der Management-Ebene - die falsche Annahme, dass<br />
jeder, der relationale Modellierung für OLTP-Systeme beherrscht, auch im Stande ist, ein gutes Star-<br />
Schema zu entwerfen.... Die Problematik von <strong>Datamarts</strong> ist viel zu unterschiedlich zur Problematik<br />
eines OLTP-Systems: wer sich Analogien zu bedienen versucht, kann die Dinge noch schlechter<br />
machen.<br />
... und warum ist diese Problemstellung so wichtig?<br />
Es geht um die Effizienz der Informatik in Data Warehouse Projekten.<br />
Praxis<strong>bei</strong>spiel1:<br />
Die Reporting Plattform eines operativen CRM – liefert pro Kunde Vermögen- und Verhaltensstatistik -<br />
ist im Unternehmen erfolgreich. Vom Management kommt ein zusätzlicher Bedarf, über diesen<br />
Datenbestand eine strategische on-line Analyse zu machen.<br />
Der erste Anlauf endet in einer Sackgasse: on-line Analyse (d.h. Spielen mit den Daten) ist nicht<br />
möglich, da die Analysten nach <strong>Antwortzeiten</strong> über 10 Minuten bereits vergessen haben, wozu sie die<br />
Frage gestellt haben ;-). Man formuliert einen Auftrag an Informatik, hier etwas zu unternehmen.<br />
Die Informatik reagiert mit einer Aufwandschätzung, die jedes denkbare Budget übersteigt. Bestehende<br />
Strukturen sind dazu nicht geeignet, man muss Neues entwickeln, dann dieses parallel zu dem<br />
Bestehenden betreiben oder aufwändig migrieren. Das Business kommt nicht aus dem Stauen: da<strong>bei</strong><br />
wollten sie nur eine neue Art der Abfragen beschleunigen....<br />
Praxis<strong>bei</strong>spiel2:<br />
Eine OLAP Plattform ist im Unternehmen für ihre interessanten Analysen und schnelle <strong>Antwortzeiten</strong><br />
beliebt. Jetzt will man, dass auch die Leute auf der Linie diese Plattform für taktische Entscheide<br />
benutzen.<br />
Man geht von der Annahme aus, dass die Informatik die Detaildaten bereits besitzt (sonst wären die<br />
OLAP Verdichtungen ja nicht möglich), und somit sollte deren Freigabe relativ kostengünstig über die<br />
Bühne gehen.<br />
Die Reaktion der Informatik ist etwa im gleichen Still wie in dem vorherigen Beispiel.<br />
Nach dieser Erfahrung fragt sich das Business berechtigt, ob die Informatik im DWH–Bereich etwas von<br />
den Software Engineering Techniken anwendet...<br />
Und was sind denn die Engineering Techniken <strong>bei</strong> der Umsetzung des dimensionalen Modells ins<br />
relationale Star-Schema? Schauen wir uns das genauer an.<br />
1 Dies <strong>bei</strong>nhaltet: atomare Daten, Indexe und materialized Views<br />
2 in Oracle mit sog. Materialized Views implementiert<br />
2/12
Relationales Star-Schema als Umsetzung des dimensionalen Modells<br />
Es gibt eine grosse Vielfalt an Quellen, welche die Grundkonzepte der Star-Schema-Modellierung<br />
beschreiben. In diesem Artikel werde ich hauptsachlich diejenigen Konzepte erläutern, die in diesem<br />
Umfeld neu sind und zugleich in die Kategorie wichtig gehören.<br />
Hier die neuen und wichtigsten Guidelines aus unserer Best-Practice:<br />
1) Surrogate Keys everywhere – auf jeder Verdichtungsstufe<br />
2) Joins, welche Selektivität des Einstiegs in Fakttabelle nicht erhöhen, vermeiden (no snowflaking)<br />
3) gefragten Gültigkeitsbezug pro Verdichtungsstufe wahrnehmen<br />
4) hohe und gleichmässige Selektivität aller Fremdschlüssel der Fakttabelle (Aggregatstabelle)<br />
anstreben<br />
Die nächsten Zeilen erläutern detailliert, worum es in den oben genannten Punkten genau geht.<br />
Guideline1: Surrogate Keys everywhere – auf jeder Verdichtungsstufe<br />
Eine Verdichtungsstufe (z.B. „Kundenstatus“) ist eine Gruppe von Dimensionsmembern („aktiv“,<br />
„aufgehoben“, „gesperrt“), welche die Kennzahlen einer oder mehrerer Faktaussagen beschreiben.<br />
Die Members haben neben einer eindeutigen Identifikations-Bezeichnung (member key), neben einem<br />
Verweis auf einem Parentmember (z.B. „alle Kundenstati“) noch bspw. eine Fliesstext-Beschreibung<br />
(member name). Die Members werden als bestimmte Attribute der Einträge einer Dimensionstabelle<br />
implementiert.<br />
Der Surrogate key ist eine nicht-sprechende Nummer (meistens von einer DB-Sequenz generiert),<br />
welche eine DWH-weit eindeutige „Addresse“ eines Members 3 (genauer: seiner Version) darstellt.<br />
Die Aufgabe von Surrogate-Keys ist inzwischen allgemein gut bekannt. Was weniger bekannt ist, dass<br />
es durchaus Sinn macht, einen (eigenständigen) Surrogate-Key für jede Verdichtungsstufe der<br />
Dimension zu implementieren (und nicht nur für die feinste Verdichtungsstufe, wie heutzutage üblich<br />
der Fall ist).<br />
Warum?<br />
Erst konsequentes „surrogate keys everywhere“ erlaubt:<br />
A) Hierarchie-Constraints <strong>bei</strong> „Slowly Changing Type 2“ Dimensionen zu deklarieren<br />
B) Kennzahlen zweier Fakttabellen unterschiedlicher Granularitätsstufe ohne nennenswerten<br />
Aufwand gegenüberzustellen<br />
Schauen wir uns die Dinge näher an:<br />
A) Hierarchie-Constraints <strong>bei</strong> „Slowly Changing Type 2“ Dimensionen werden möglich<br />
Hierarchie-Constraints werden in Oracle mittels CREATE DIMENSION Befehl deklariert. Abbildung 1<br />
stellt eine Beispielshierarchie dar. Der entsprechende Quellcode für CREATE DIMENSION Befehl ist im<br />
Quellcodeauszug 1 zu finden.<br />
3 oder einer Memberskombination – siehe weiter<br />
3/12
{ }<br />
{ }<br />
{ }<br />
Organisations<br />
struktur<br />
Organisations<br />
struktur<br />
Bereich<br />
Abteilung<br />
Mitar<strong>bei</strong>ter<br />
Abbildung1: Beispielshierarchie in der Dimension „Organisationsstruktur“ in der ADAPT Notation<br />
CREATE DIMENSION dim_OrgStruktur<br />
LEVEL mitar<strong>bei</strong>ter IS DIM_ORGSTRUKTUR.MITARBEITER_NR -- NR vom HR<br />
LEVEL abteilung IS DIM_ORGSTRUKTUR.ABTEILUNG_CODE -- CODE vom HR<br />
LEVEL bereich IS DIM_ORGSTRUKTUR.BEREICH_CODE -- CODE vom HR<br />
HIERARCHY hier_OrgStruktur (<br />
mitar<strong>bei</strong>ter CHILD OF<br />
abteilung CHILD OF<br />
bereich )<br />
ATTRIBUTE mitar<strong>bei</strong>ter DETERMINES<br />
(MITARBEITER_NAME, MITARBEITER_VORNAME, MITARBEITER_GEBURTSJAHR)<br />
ATTRIBUTE bereich DETERMINES<br />
......<br />
;<br />
Quellcodeauszug1: CREATE DIMENSION Befehl zur Deklaration der Hierarchie Organisationstrukur<br />
Die Hierarchie-Constraints dienen dazu, der „Query-Rewrite“ Erweiterung vom CBO 4 mitzuteilen, dass<br />
sie für Abfragen auf der Stufe „Bereich“ auch solche MViews benutzen kann, welche die<br />
Mitar<strong>bei</strong>terkennzahlen - aggregiert auf Stufe „Abteilung“ - enthalten.<br />
Bei “Slowly Changing Dimensionen Typ 2“ 5 braucht man nach einem Wechsel einer Abteilung (z.B.<br />
der Abteilung “DWH-Entwicklung”) von einem Bereich zu einem Anderen <strong>bei</strong>de Versionen dieser<br />
Abteilung abzuspeichern: Eine für die Fakten vor dem Wechsel und die Andere für die Fakten danach.<br />
(siehe Abbildung 2).<br />
4 cost based optimizer<br />
5 Terminologie wurde vom Ralph Kimball eingeführt, für kürze Erklärung siehe nächstes Guideline<br />
4/12
Abbildung2: Datensätze der Dimension „dim_OrgStruktur“<br />
Ein Hierarchie-Constraint, welcher über den Member-Keys der Stufen „Abteilung“ und „Bereich“<br />
deklariert ist (Quellcodeauszug1), wäre nach dem Wechsel der Abteilung verletzt (Abteilung „DWH-<br />
Entwicklung“ gehört dann zu zwei Bereichen: nämlich „INF“ und „BIC“).<br />
Dieses Problem kann eliminiert werden, in dem man Surrogate-Keys auf jeder Stufe einführt und<br />
anschliessend die Hierarchie-Constraints als im Quellcodeauszug 2 deklariert (die Surrogate-Keys<br />
entsprechen der Namenskonvention „DWH_ID_“)<br />
CREATE DIMENSION dim_OrgStruktur<br />
/* in dieser Form unterstützt auch SCD Typ 2 */<br />
LEVEL version_mitar<strong>bei</strong>ter IS DIM_ORGSTRUKTUR.DWH_ID_MITARBEITER -- SurrogKey<br />
LEVEL mitar<strong>bei</strong>ter IS DIM_ORGSTRUKTUR.MITARBEITER_NR -- NR vom HR<br />
LEVEL version_abteilung IS DIM_ORGSTRUKTUR.DWH_ID_ABTEILUNG -- SurrogKey<br />
LEVEL abteilung IS DIM_ORGSTRUKTUR.ABTEILUNG_CODE -- HR-CODE<br />
LEVEL version_bereich IS DIM_ORGSTRUKTUR.DWH_ID_BEREICH -- SurrogKey<br />
LEVEL bereich IS DIM_ORGSTRUKTUR.BEREICH_CODE -- HR-CODE<br />
HIERARCHY hier_MAversion_MA (<br />
version_mitar<strong>bei</strong>ter CHILD OF<br />
mitar<strong>bei</strong>ter )<br />
HIERARCHY hier_MAversion_abteilung (<br />
version_mitar<strong>bei</strong>ter CHILD OF<br />
version_abteilung CHILD OF<br />
abteilung )<br />
HIERARCHY hier_MAversion_bereich (<br />
version_mitar<strong>bei</strong>ter CHILD OF<br />
version_abteilung CHILD OF<br />
version_bereich CHILD OF<br />
bereich )<br />
ATTRIBUTE mitar<strong>bei</strong>ter DETERMINES<br />
(MITARBEITER_NAME, MITARBEITER_VORNAME, MITARBEITER_GEBURTSJAHR)<br />
ATTRIBUTE bereich DETERMINES<br />
......<br />
;<br />
Quellcodeauszug 2: „CREATE DIMENSION“ zur Deklaration der Hierarchie Organisationstrukur vom<br />
SCD Typ 2<br />
B) Gegenüberstellung der Kennzahlen zweier Fakttabellen unterschiedlicher Granularitätsstufe<br />
mit wenig Aufwand möglich<br />
5/12
Diesen Vorgang ist am einfachsten anhand eines Beispiels zu erklären.<br />
Abbildung 3 zeigt die Situation auf.<br />
Abbildung 3: Fakttabelle „Erträge“ und Fakttabelle „Kosten“ teilen neben der Zeit auch die Hierarchie<br />
„Produkttyp“<br />
Nehmen wir weiter an, die Erträge sind im OLTP System auf der Stufe „Einzelprodukt“ vorhanden, die<br />
Kosten jedoch nur auf der Stufe „Produkttyp“.<br />
Dieses Beispiel kann mit dem Ansatz „Surrogate Keys auf jeder Verdichtungsstufe“ wie folgt<br />
implementiert werden:<br />
Über der Dimensionstabelle „DIM_PRODUKT“ sind folgende Hierarchie-Constraints deklariert:<br />
CREATE DIMENSION dim_Produkt<br />
/* unterstützt auch SCD Typ 2 */<br />
LEVEL version_einzelprodukt IS DIM_PRODUKT.DWH_ID_EINZELPRODUKT -- SurrogKey<br />
LEVEL einzelprodukt IS DIM_PRODUKT.PROD_SERIAL# -- OLTP-Key<br />
LEVEL version_produkttyp IS DIM_PRODUKT.DWH_ID_PRODUKTTYP -- SurrogKey<br />
LEVEL produkt IS DIM_PRODUKT.PRODUKTTYP_CODE -- OLTP-Key<br />
LEVEL version_produktart IS DIM_PRODUKT.DWH_ID_PRODUKTART -- SurrogKey<br />
LEVEL produktart IS DIM_PRODUKT.PRODUKTART_CODE -- OLTP-Key<br />
HIERARCHY hier_EPversion_EP (<br />
version_einzelprodukt CHILD OF<br />
einzelprodukt )<br />
HIERARCHY hier_EPversion_produkttyp (<br />
.... )<br />
......<br />
;<br />
6/12
Die Fakttabelle „FaktProduktErträge“ verweisst auf das Attribut DWH_ID_EINZELPRODUKT, das den<br />
Primärschlüssel der Dimensionstabelle „DIM_PRODUKT“ bildet.<br />
Die Fakttabelle „FaktProduktKosten“ verweisst auf das Attribut DWH_ID_PRODUKTTYP, das den<br />
Primärschlüssel der Tabelle „DIM_PRODUKTTYP“ bildet. Für diese Tabelle ist kein Ladejob nötig, da<br />
sie die Materialisierung (Materialisierte View) der folgenden Abfrage über der Tabelle<br />
„DIM_PRODUKT“ ist:<br />
SELECT DISTINCT<br />
DWH_ID_PRODUKTTYP,<br />
PRODUKTTYP_CODE,<br />
... alle anderen vom PRODUKTTYP_CODE abhängige Attribute<br />
FROM DIM_PRODUKT<br />
Die Tatsache, dass <strong>bei</strong>de Fakttabellen die Verdichtungsstufe Produkttyp teilen, ist mittel eines<br />
gemeinsamen SurrogateKeys DWH_ID_PRODUKTTYP implementiert. Dies deutet darauf hin, dass<br />
Kosten/Ertragsvergleiche möglich sind. Falls diese öfters abgefragt werden, soll ein gespeichertes<br />
Aggregat (materialisierte View) über der Fakttabelle „FaktProduktErträge“ auf Stufe<br />
DWH_ID_PRODUKTTYP angelegt werden.<br />
Wie wir gesehen haben, fordert die Technik „surrogate keys everywhere“ indirekt, in sog. konformen<br />
Verdichtungsstufen 6 zu denken.<br />
Guideline2: „no snowflaking“: Vermeidung von Joins, welche Selektivität des<br />
Einstiegs in Fakttabelle nicht erhöhen<br />
Snowflaking ist eine Technik, <strong>bei</strong> der die Attribute von Members der höheren Verdichtungsstufen,<br />
deren Werte in der Dimensionstabelle vielfach wiederholt werden, in eine separate Tabelle ausgelagert<br />
(normalisiert) werden.<br />
Auch wenn Herr Kimball bereits vor vielen Jahren geschrieben hat „Efforts to normalize dimension<br />
tables in order to save disk space are a waste of time“, es gibt immer noch vielerorts Bedenken, ob dies<br />
<strong>bei</strong> relationalen Systemen wie Oracle gilt.<br />
Deswegen wiederhole ich hier die Begründung, warum ein „snowflaking“ in <strong>Datamarts</strong> punkto<br />
Abfrageperformance kontraproduktiv ist:<br />
Jeder Join in einer Abfrage bedeutet lediglich ein Mehraufwand ohne einen Mehrwert, solange durch<br />
diesen Join kein selektiver 7 Einstieg in die Fakttabelle geschaffen wird.<br />
Aus einer Dimensionstabelle können in eine Snowflake-Tabelle nur Daten der höheren<br />
Verdichtungsebenen ausgelagert werden, die ja aufgrund ihrer Natur immer nur weniger selektiv sind<br />
(es gibt meistens weniger Produkttypen als Produkte).<br />
Snowflaking bringt somit Mehraufwand für zusätzlichen Join, dem punkto Performance keinerlei<br />
Mehrwert gegenübersteht.<br />
Wie soll man „surrogate keys everywhere“ einerseits und „no snowflaking“ andererseits denn<br />
verstehen?<br />
6 eine Erweiterung des Konzepts “conform dimensions” vom Kimball<br />
7 selektiver Einstieg: eine Einschränkung in der WHERE Klausel, welche veranlasst, dass ein Zugriff via<br />
Index kostengünstiger ist als die ganze Tabelle(Tabellenpartition) zu lesen. Im DWH-Bereich kann man<br />
von der Daumenregel (hängt natürlich von Fakttabellengrösse und z.V. stehenden HW ab) ausgehen,<br />
dass ein Index-Zugriff dann günstiger ist, falls weniger als 1% der Faktdaten gelesen werden sollen.<br />
7/12
„Surrogate Keys auf jeder Verdichtungsstufe“ definiert, wie die Dateninhalte identifiziert (adressiert)<br />
werden. „No snowflaking“ beschreibt, wie die Dateninhalte gespeichert werden. Der Quellcode fürs<br />
Dimensionsladen kann <strong>bei</strong> sauberer Trennung dieser zwei Dinge leicht komplexer sein (als <strong>bei</strong> heute<br />
verbreiteten „Beides-Ist-Eigentlich-Das-Gleiche“-Ansatz), ist aber standardisierbar und sogar<br />
automatisierbar… von dem her, kein wirklicher Zuwachs an Entwicklungskosten – nur an<br />
Entwicklungsdisziplin.<br />
Guideline3: Gefragten Gültigkeitsbezug pro Verdichtungsstufe wahrnehmen<br />
In der Phase „dimensionale Modellierung“ wurde <strong>bei</strong> einzelnen Verdichtungsebenen u.a. auch der sog.<br />
Gültigkeitsbezug (oder auch Typ der Slowly Changing Dimension 8 ) mit dem Endbenutzer festgelegt:<br />
1) Stand gemäss letzter Dimensionsaktualisierung (Kimball’s Typ 1)<br />
2) effektiver Stand damals (Kimball’s Typ 2)<br />
3) Stand zum eingefrorenen historischen Zeitpunkt<br />
Eine kurze Erklärung und Aufzeigen der Eigenschaften der einzelnen Bezugstypen werde ich anhand<br />
der Mitar<strong>bei</strong>ter-Hierarchie „Organisationsstruktur“ aus der Abbildung 1 machen.<br />
Nehmen wir weiter an, man möchte den „Produktumsatz“ messen, den die einzelnen Mitar<strong>bei</strong>ter<br />
verkauft haben.<br />
Beobachten wir mal die Beispielssituation, dass ein Mitar<strong>bei</strong>ter per 01.03.2004 die Abteilung von „X“<br />
auf „Y“ gewechselt hat.<br />
1) Stand gemäss letzter Dimensionsaktualisierung (Kimball’s Type 1)<br />
Der Umsatz des Mitar<strong>bei</strong>ters sowohl vor dem 01.03.2004 als auch nach dem 01.03.2004 wird der letzt<br />
gültigen Abteilung, d.h. „Y“ angerechnet. Dieser Bezugstyp wird auch konsolidierte Sicht genannt.<br />
Neben<strong>bei</strong>: Gespeicherte Aggregate, welche eine solche Verdichtungsebenen aufaggregiert haben,<br />
werden meistens günstiger mit einem Full Refresh aktualisiert. Generell ist hier ein Refresh „teuer“.<br />
2) effektiver Stand damals (Kimball’s Typ 2)<br />
Der Umsatz des Mitar<strong>bei</strong>ters vor dem 01.03.2004 wird der Abteilung „X“ angerechnet, der Umsatz<br />
danach der Abteilung „Y“.<br />
Neben<strong>bei</strong>: Fakttabelle oder Aggregate, welche ausschliesslich solche Verdichtungsebenen<br />
„referenzieren“, können mit einem inkrementellen Refresh geladen werden (günstiger Refresh der<br />
gespeicherten Aggregate).<br />
3) Stand zum eingefrorenen historischen Zeitpunkt (bspw. Jahresbeginn)<br />
Der Umsatz des MAs wird vom 01.01.2004 bis 31.12.2004 der Abteilung „X“ angerechnet. Der<br />
Umsatz ab 01.01.2005 wird der Abteilung „Y“ angerechnet.<br />
Neben<strong>bei</strong>: Fakttabelle oder Aggregate, welche ausschliesslich solche Verdichtungsebenen<br />
„referenzieren“, können mit einem inkrementellen Refresh geladen werden.<br />
Diese Art des Bezugs wird vor allem im taktischen DSS gefragt, wo Plan-Ist Vergleiche die gleiche<br />
Ausgangslage verlangen.<br />
Bei <strong>Datamarts</strong>, welche sowohl taktische Entscheidungsfindung als auch strategische Analyse<br />
unterstützen sollen, kann es vorkommen, dass gewisse Verdichtungsebenen zweimal angeboten<br />
werden.<br />
Bsp: Im Datamart „Kontotransaktionen“ kann das Kundensegment zweimal vorkommen:<br />
- „Kundensegment“ (effektiver Stand damals)<br />
8 Slowly Changing Dimension – kurz SCD<br />
8/12
- „Kundensegment per Jahresbeginn“<br />
Es handelt sich um zwei Dimensionen, deren Inhalt und Struktur identisch ist (d.h. zwei Views auf eine<br />
Dimensionstabelle, zwei Verweise von den Fakteinträgen)<br />
Vermutlich ist mehreren von Ihnen folgendes bekannt: Solange in der Fakttabelle der Bezugstyp 2<br />
(effektiver Stand damals) implementiert ist, kann man die Kennzahlen jederzeit in die anderen<br />
Bezugstypen transformieren (vorausgesetzt die Dimension enthält die Gültigkeitseinschränkungen der<br />
Versionen, sog. Valid_from & Valid_to).<br />
Auch wenn die Mittel dies zu tun meistens zur Verfügung stehen (DB-Views oder BO-Universen),<br />
unsere Erfahrung zeigt, dass es nicht sinnvoll ist, dies zu tun, denn die Performance dieser Abfragen<br />
wird stark leiden:<br />
- die betroffene Dimensionstabelle muss zweimal gejoint werden<br />
- eine Star-Transformation ist hier meistens ausgeschlossen<br />
- die Schwachstelle vom Oracle-CBO „keine Berechnung von Statistiken für<br />
zusammengesetzte Felderkombinationen möglich“ kommt zum Vorschein.<br />
Wer mit der on-the-fly Ableitung (zur Abfragezeit: DB-View oder BO-Prädikat) an Speicherplatz der<br />
Fakttabelle sparen möchte, spart auf der falschen Stelle.<br />
Unsere Praxis zeigt weiter, dass es aus Bewirtschaftungsgründen nicht günstig ist, Verdichtungsstufen<br />
unterschiedlicher Bezugstypen (z.B. Typ1 zusammen mit Typ2) in eine Dimensionstabelle abzulegen.<br />
Daher ist es wichtig, <strong>bei</strong>m Design der Dimensionstabelle die Bezugstypen wahrzunehmen, und in eine<br />
Dimensionstabelle nur Verdichtungsebenen gleicher Bezugsart unterbringen.<br />
Guideline4: hohe und gleichmässige Selektivität aller Fremdschlüssel der<br />
Fakttabelle (Aggregatstabelle) anstreben<br />
Im vorherigen Artikel habe ich den Ansatz zur Auflösung der „slowly changing monster dimensions“<br />
erklärt (Abbildung 3 zeigt das Resultat). Wie man aus der Abbildung sehen kann, endete ich mit einer<br />
grösseren Anzahl kleiner Dimensionen.<br />
{ }<br />
Einzelkunde<br />
Einzelkunde<br />
Kundennummer<br />
{ }<br />
Kunden<br />
segment<br />
Markt<br />
segment<br />
Kundensegment Marktsegment<br />
Kundensegment<br />
{ }<br />
Marktsegment<br />
{ }<br />
{ }<br />
{ }<br />
Kunden<br />
Wohnort<br />
Wohnort<br />
Geographie<br />
Land<br />
Kanton<br />
Ort<br />
{ } OECD<br />
Mitglied<br />
PLZ<br />
Wohnort<br />
Verkaufs<br />
region<br />
Verkaufs<br />
region<br />
Verkaufs { } region<br />
{ }<br />
Kunden<br />
Status<br />
Status Sprache<br />
Status<br />
{ }<br />
Korrespondenz<br />
Sprache<br />
Sprache<br />
Kundenbranche<br />
Kundenbranche<br />
{ } Abteilung<br />
Kundenbranche<br />
{ } Gruppe<br />
Kundenbranche<br />
{ } Klasse<br />
{ }<br />
Kunden<br />
Branche<br />
Kundenbranche<br />
Alter<br />
Nationalität<br />
{ } Altersegment { } Nationalität<br />
{ }<br />
Alter Nationalität Geschlecht<br />
Abbildung3: Auslagern der hoch-kardinalen Verdichtungsstufe Einzelkunde in separate Dimension<br />
Bei vorheriger Guideline (3) habe ich erwähnt, dass es - Benutzerbedarf vorausgesetzt – sinnvoll ist, die<br />
Dimension „Kundensegment“ auf zwei Dimensionen „Kundensegment (jeweils zum Faktdatum gültig)“<br />
und „Kundensegment per Jahresbeginn“ aufzuspliten. Dies trägt zur Erstellung noch weiterer<br />
Dimensionen <strong>bei</strong>.<br />
Geburtsjahr<br />
{ }<br />
9/12<br />
Geschlecht<br />
Geschlecht
Die Aufgabe der relationalen Modellierung liegt u.a. auch dort, die Faktverbindungen zu all diesen<br />
(vielen) Dimensionen abzuspeichern. Dies jedoch in solcher Form, dass:<br />
- selektive 9 Abfragen wenig I/O benötigen<br />
- der Platzbedarf für die Fakttabelle im vertretbaren Ausmass bleibt<br />
Wie wir bereits wissen gibt es <strong>bei</strong> <strong>Datamarts</strong>, welche taktisches Reporting oder DSS unterstützen,<br />
meistens eine Dimension, welche die Kardinalität 10 der Fakttabelle massgeblich bestimmt. Beispiel:<br />
„Einzelkunde“ - es gibt durchschnittlich nur etwa 100-200 Transaktionen pro „Einzelkunde“, obwohl es<br />
einige Millionen von Einzelkunden mit einer Transaktion gibt.<br />
Hätte ich in diesem Datamart <strong>bei</strong>m relationalen Design einfach für jede kleine Dimension eine<br />
Dimensionstabelle gemacht, dann würden die Attribute der Fremdschlüssel (oder sogar Attribut-<br />
Kombinationen) extrem wenig selektiv, da<strong>bei</strong> aber wesentlich (aufgrund ihrer grösseren Anzahl) zur<br />
Breite des Fakteneintrags – und somit auch dem Bedarf an Diskplatz – <strong>bei</strong>tragen. Die meisten von<br />
Ihnen sehen es ein – es nicht so zu machen.<br />
Die Lösung hier heisst: junk dimension tables 11 (Dimensionen-Zusammenschluss in eine Tabelle):<br />
Ich nehme einige der kleinen Dimensionen (mit wenigen Members, am besten nur mit einer<br />
Verdichtungstufe), mache ein kartesisches Produkt von den Members der Dimensionen (Kombination<br />
jeder mit jedem), erzeuge einen neuen Surrogate-Key-Wert für jede Kombination, und schreibe die<br />
Kombination in eine Dimensionstabelle (junk dimension table).<br />
Zugegeben, der Refresh-Algorithmus für eine solche Junk Dimensionstabelle ist um einiges komplexer<br />
(punkto Entwicklung aufwändiger) als einfach für jede Dimension eine Dimensionstabelle zu haben.<br />
Der Zweck von <strong>Datamarts</strong> liegt jedoch nicht darin, dass es die Entwickler einfach haben, sondern dass<br />
die Endbenutzer performante Abfragequelle haben.<br />
Wenn wir jetzt die Technik von junk dimension tables verstehen, kommen wir zu der methodischen<br />
Frage: wann soll man „junk dimension tables“ verwenden und welche Dimensionen zusammenfassen?<br />
Hier ein paar Tipps:<br />
1) Zusammenschluss mit Dimension „Zeit“ vermeiden<br />
… ist ja irgendwie logisch. Dimension „Zeit“ hat eine Reihenfolge unterhalb der Members: Diese kann<br />
man neben der Performance (Partition-Elimination über range-partitionierter Tabelle) auch für Admin-<br />
Zwecke (Partition auf read-only setzen, droppen) gut gebrauchen.<br />
2) Zusammenschluss von Dimensionen mit mehreren oder mehrstufigen Hierarchien vermeiden<br />
Die Ladenprozeduren (wenn sie noch die gefragte Bezugsart richtig implementieren) sind hier ohnehin<br />
schon genug komplex, um da noch die zusätzliche Komplexität vom Zusammenschluss einzuführen.<br />
Meistens haben diese Dimensionen ohnehin schon grössere Anzahl vom Members (1000+) auf der<br />
feinsten Verdichtungsstufe. Somit ist es mit der tiefen Selektivität nicht so schlimm und daher ist auch<br />
der Handlungsbedarf hier klein ist.<br />
3) Dimensionen vom Typ 1 (overwriting history) lassen sich nicht zusammenschliessen (junken)<br />
4) Zusammenschluss der fachlich zusammengehörenden Dimensionen bevorzugen<br />
9 nicht-selektive Abfragen sollen mit geeigneten gespeicherten Aggregaten (MViews) unterstützt werden<br />
10 d.h. Anzahl Rows pro Zeit-Member (Zeitpunkt, Zeitperiode)<br />
11 Begriff eingeführt vom Ralph Kimball<br />
10/12
Dimensionen, welche aufgrund ihres Inhalts oder der Abfragemethode (strategisch/taktisch)<br />
zusammengehören, sind geeignete Kandidaten für den Zusammenschluss.<br />
Das Vorgehen ist aus der Abbildung 4 ersichtlich.<br />
Einzelkonto<br />
Kundenkonten<br />
Kontoinhaber<br />
{ } (Einzelkunde)<br />
{ }<br />
6 Mio<br />
Einzelkonto<br />
{ }<br />
Kundennummer<br />
Kontonummer<br />
Kundensegment Marktsegment<br />
Kunden<br />
segment<br />
{ }<br />
{ }<br />
{ }<br />
Zeit<br />
Kalenderjahre<br />
48<br />
{ }<br />
Quartal<br />
Quartal<br />
Jahrmonat<br />
Markt<br />
segment<br />
<strong>Teil</strong>markt der<br />
Produktkategorie<br />
<strong>Teil</strong>markt der<br />
{ } Produktkategorie<br />
{ }<br />
Kunde Wahrnehmungsprofil<br />
{ }<br />
Finanzprodukt<br />
Produktkategorie<br />
{ }<br />
Kontotyp<br />
Kontotyp<br />
Kontoart<br />
Kundenausrichtung<br />
Kunden- { } ausrichtung<br />
Währung<br />
Währung<br />
{ } Produkt<br />
{ }<br />
Kontoart<br />
{ } Status<br />
Produkt<br />
beschreibung<br />
50<br />
40 10<br />
{ }<br />
Kundensegment<br />
Marktsegment<br />
Verkaufs<br />
region<br />
Status<br />
12 7 10 10<br />
Verkaufs<br />
region<br />
Verkaufs<br />
region<br />
(Stand zum Faktzeitpunkt)<br />
(Stand zum Jahresbeginn)<br />
Status<br />
Kunden<br />
Status<br />
Kontoeingenschaften<br />
Kontokennzahlen<br />
Saldo Bodensatz CHF<br />
.....<br />
{ }<br />
Sprache<br />
Sprache<br />
Korrespondenz<br />
Sprache<br />
{ }<br />
{ }<br />
Kundeneigenschaften<br />
Geburtsjahr<br />
{ } Altersegment { } Nationalität<br />
Alter<br />
110<br />
Nationalität<br />
Kontostatus<br />
Status<br />
{ }<br />
Geschlecht<br />
6 150 4<br />
Geschlecht<br />
Alter Nationalität Geschlecht<br />
{ }<br />
{ }<br />
{ }<br />
Kundenbranche<br />
Kundenbranche<br />
{ } Abteilung<br />
Kundenbranche<br />
{ } Gruppe<br />
Kundenbranche<br />
{ } Klasse<br />
Abbildung4: Dimension-Junking der fachlich zusammengehörenden Dimensionen<br />
{ }<br />
6700<br />
Kunden<br />
Branche<br />
Kundenbranche<br />
Ort<br />
Kanton<br />
Land<br />
170<br />
Wohnort<br />
Geographie<br />
Kunden<br />
Wohnort<br />
11/12<br />
PLZ<br />
Wohnort<br />
{ } OECD<br />
Mitglied<br />
Beispiele: Kleindimensionen über Kunden in Junk-Dimension-Table „Kundenprofil“<br />
zusammenschliessen.<br />
Analog <strong>bei</strong> Kleindimensionen des Kontos. Neben dem „Kundenprofil“ (für strategische Abfragen oder<br />
operative Zwecke) ggf. noch „Kundenprofil (per Jahresbeginn)“ für taktische Abfragen erstellen.<br />
5) Diskplatzersparnis im Kontext der Komplexitätssteigerung abwägen<br />
Fakttabellen können heutzutage 12 <strong>bei</strong> gutem Clustering Faktor sehr effizient komprimiert werden (data<br />
segment compression).<br />
Das Erhöhen vom Clustering Faktor und die Kompression sind fast gratis (wir bezahlen Oracle die<br />
Lizenzkosten so oder so). Das Dimension-Junking führt zwar zum grösseren Platzersparnis, steigert aber<br />
die Komplexität und somit auch die ETL-Entwicklungskosten.<br />
Am Schluss noch ein Tipp fürs ETL:<br />
Refresh einer „junk dimension table“ soll immer im letzten Schritt die Eindeutigkeit der Member-Key-<br />
Kombinationen prüfen. Falls die Dimensionstabelle nur wenige Einträge enthält, kann dies ein Unique<br />
Constraint (Unique Index) übernehmen. Beispiel: KUNDENSEGMENT_CODE und<br />
MARKTSEGMENT_CODE sind die Member-Keys der (allen) zweit Verdichtungsstufen, welche in<br />
Tabelle DIM_SEGMENT zusammmengefasst wurden. Ein Unique Index (KUNDESEGMENT_CODE,<br />
MARKTSEGMENT_CODE) über dieser Dimensionstabelle sichert, dass ein Look-Up für Surrogate-Key<br />
<strong>bei</strong> Laden der Fakteinträge höchstens eine Row liefert.<br />
12 Oracle 9.2 oder höher
Zusammenfassung<br />
Anhand einiger Praxis<strong>bei</strong>spiele hat dieser Artikel die Wichtigkeit der Designar<strong>bei</strong>t <strong>bei</strong>m Aufbau eines<br />
<strong>Datamarts</strong> demonstriert.<br />
Unsere Erfahrung zeigt, dass viele Kunden <strong>bei</strong>m Design oder Redesign der <strong>Datamarts</strong> dieser Phase<br />
vermehrt erhöhte Aufmerksamkeit widmen: nämlich solche, die sie aufgrund der weitreichenden<br />
Entscheide verdient.<br />
Ich würde mich über Anregungen, Kommentare und Erfahrungen zu diesem Artikel erfreuen.<br />
In den nächsten Artikeln werde ich mich dem physischen Design widmen.<br />
Viel Erfolg <strong>bei</strong>m (Um)bau Ihrer <strong>Datamarts</strong> wünscht<br />
Karol Hajdu<br />
karol.hajdu@trivadis.com<br />
<strong>Trivadis</strong> AG<br />
Europa-Strasse 5<br />
CH – 8152 Glattbrugg<br />
Tel. +14 1 808 70 20<br />
12/12