| von Philipp Labatzki

Tableaus Datenmodell im Umgang mit multiplen Faktentabellen und Shared Dimensions

Seit der Version 2020.2 ist das Relationen-Datenmodell Bestandteil des Tableau Desktop und erlaubt es, neben klassischen Joins nun auch Beziehungen zwischen Tabellen zu bilden. Dies ermöglicht vor allem flexiblere Auswertungen mit unterschiedlichsten Granularitäten innerhalb Tableaus ohne die Verwendung von Detailgenauigkeitsausdrücken (LoD / Level of Detail-Formeln).

Erstellt man sich eine eigene Tableau Datenquelle im Relationen-Modell, umfasst diese in vielen Fällen Fakten- und Dimensionstabellen, die miteinander verknüpft werden sollen. Liegen hierbei mehr als eine Dimensionstabelle vor, die mit mehreren unterschiedlichen Faktentabellen verknüpft werden sollen, kommt schnell die Frage nach der optimalen Modellierung im Relationen-Modell auf.

Symbolbild
Abbildung 1: Symbolbild

Grundsätzlich lässt sich dieser beschriebene Fall auch im klassischen Modell (physischen Layer) mit Joins darstellen, solange die Faktentabellen die gleiche Granularität aufweisen. Andernfalls ist die Verwendung von LoDs notwendig. Doch gerade um letzteres zu vermeiden, ist eine Lösung im Relationen-Modell wünschenswert. Die Modellierung mit mehreren Faktentabellen, die wiederum mit mehreren gemeinsamen Dimensionstabellen (Shared Dimensions) verknüpft werden, wird jedoch nicht unterstützt.[1] Das heißt eine 1:1 Modellierung, wie in Abb. 1 dargestellt, ist nicht möglich. Warum? Die Ursache hierin liegt in dem Festlegen von nur einer Basistabelle(siehe Abb.2: Dimension 1), die als erste im logischen Layer platziert wird und dem damit nicht möglichen Bilden von Circular Relationships.[2] [3]

Nachbildung Problemfall
Abbildung 2: Logischer Layer Nachbildung Problemfall

Eigentlich wäre es also notwendig, von einer Entität - entweder den Fakten oder den Dimensionen – aus, zwei Relationen nach links auszuprägen. Genau dies ist aber im Relationen-Modell nicht möglich.

Oft wird dieses Problem umgangen, in dem die Dimensionen innerhalb der Faktentabelle integriert werden, sodass nur die Faktentabellen miteinander verknüpft werden müssen und folgendes Relationen-Modell resultiert:

Layer Dimensionen
Abbildung 3: Logischer Layer Dimensionen in Fakten integriert

Jedoch gilt dies als problematisch, wenn nicht eine Faktentabelle die Obermenge an gemeinsamen Dimensionen hat, bzw. die Tabellen viele unterschiedliche Dimensionsausprägungen haben [4]. Dies würde dazu führen, dass für jede geteilte Dimension eine IFNULL Berechnung erstellt werden müsste, um abzufragen, ob die Ausprägung nur in Fakt 1 oder nur in Fakt 2 auftritt. Welche Alternativen gibt es hierzu?

Lösungsansatz

Wie bereits beschrieben, lässt sich nur eine logische Tabelle im Relationen-Modell als Basistabelle definieren. Der Ansatz, der in diesem Artikel untersucht wird, berücksichtigt deshalb alle Dimensionen innerhalb einer einzigen logischen Tabelle und setzt diese in Relation zu den Fakten.

Layern Lösungsansatz
Abbildung 4: Logischer Layer Lösungsansatz

Wie lässt sich dieser Ansatz mittels verschiedener Wege in Tableau realisieren und welcher verspricht - auch im Vergleich mit den klassischen LoDs - möglichst wenige Einschnitte in der Performance?

Datenbasis

Zur Generierung eines Beispieldatensatzes wurde das Data Prep Tool Alteryx Designer verwendet.

Workflow
Abbildung 5: Workflow zur Datengenerierung

Der Datensatz umfasst drei Dimensionstabellen sowie zwei Faktentabellen, die alle in csv-Dateien gespeichert wurden.

Tabelle

Anzahl Datensätze

Dim_Produkt

1.600

Dim_Kunde

1.200

Dim_Zeit

365

Fakt_Ist

140.160.000

Fakt_Plan

38.400

 

Die beiden Faktentabellen weisen unterschiedliche Granularitäten auf, da die Daten aus Fakt_Ist auf der Basis von Kunden und die der Fakt_Plan hingegen auf Basis der aggregierten Kundenkategorie vorliegen:

Abbildung Datenmodell
Abbildung 6: Datenmodell

Somit unterscheiden sich beide Faktentabellen in ihrer Beziehung zur Kundenhierarchie. Für die anderen beiden Dimensionen (Produkt und Datum) gelten sowohl für Fakt_Ist als auch Fakt_Plan die gleiche Granularität in den Join-Kriterien.

In Hinblick auf die referentielle Integrität weisen alle Dimensionen aus den Faktentabellen ein Gegenstück in den Dimensionstabellen auf. Jedoch liegen nicht zwangsläufig alle möglichen Dimensionselemente in den Fakten vor.

Die im Eingang benannte Problemstellung lässt sich somit mit den generierten Daten nachbilden. Wie bereits beschrieben, kann dabei nicht jede Tabelle eine eigene logische Tabelle im Layer darstellen, da die Verknüpfungen so nicht richtig gebildet werden könnten. Ziel ist es daher, eine einzige logische Tabelle zu definieren, die sich aus allen geteilten Dimensionen zusammensetzt.

Welche Modellierungsmöglichkeiten bestehen hierfür in Tableau?

Modellierung

Bei der Modellierung der Datenquelle in Tableau wurden drei unterschiedliche Vorgehen im Vergleich verprobt: zwei verschiedene Varianten des beschriebenen Lösungsansatzes über einen Cross Join aller geteilten Dimensionen sowie zur Gegenüberstellung eine Variante mit der Verwendung von LoDs. Ein Cross Join kombiniert dabei sämtliche Elemente aller Dimensionen miteinander, ungeachtet dessen, ob diese Kombinationen in den Fakten vorkommen oder nicht.

1. Cross Join aller Dimensionen innerhalb einer logischen Tabelle

In diesem Ansatz werden alle Ausprägungen der Dimensionstabellen in einer logischen Tabelle mit einem Cross Join zusammengeführt.

Layer Cross Join
Abbildung 7: Physischer Layer Cross Join

Tableau bietet keine Möglichkeit, einen Cross Join direkt im physischen Layer anzulegen. Technisch erfolgt dieser aber, sobald ein Join-Kriterium gewählt wird, dass zwangsläufig immer erfüllt ist. Hier wurde daher das Kriterium  1=1 gewählt.  Aus diesem Kreuzprodukt resultiert eine Datenmenge von ca. 700 Mio. Zeilen. Die mit dem Cross Join definierte logische Tabelle ‚Dim (CrossJoin)‘ wird unter Berücksichtigung der Kardinalität und referentiellen Integriät im logischen Layer mit den beiden Faktentabellen verbunden.

Logischer Layer Cross Join
Abbildung 8: Logischer Layer Cross Join

2. Cross Join bereits in Datensatz durchgeführt (All_Dim)

Diese Variante unterscheidet sich lediglich vom ersten Ansatz darin, dass der Cross Join bereits im Vorfeld durchgeführt wurde und eine physische Gesamttabelle mit den knapp 700 Mio. Einträgen vorliegt. Somit wird die logische Tabelle in diesem Fall mit nur einer csv-Datei definiert:

Layer all-Dim
Abbildung 9: Phyischer Layer all_Dim

Auch diese wird wieder im logischen Layer, analog zum ersten Ansatz, mit den Faktentabellen verbunden.

Layer all-Dim
Abbildung 10: Logischer Layer All_Dim

3. Bilden von LoD Berechnungen für die Kennzahlen (LoD)

Im Vergleich zu den dargestellten Ansätzen wird ebenso der alternative Weg ohne Verwendung des Relationen-Modells untersucht. Hierbei werden alle relevanten Dimensions- und Faktentabellen im physischen Layer miteinander gejoint (Plan ist auch mit Dim_Zeit und Dim_Produkt verbunden, wird von Tableau aber nicht dargestellt).

Layer LoD
Abbildung 11: Physischer Layer LoD

Somit liegt nur eine logische Tabelle vor, die nicht in Beziehung zu anderen steht:

Layer LoD
Abbildung 12: Logischer Layer LoD

Die Werte aus der Plan Faktentabelle werden durch die Verknüpfung im physischen Layer vervielfacht, da innerhalb einer Kundenkategorie (Join-Kriterium für Fakt_Plan) mehrere Kunden auftreten können.  Um nicht Duplikate dieser Art in die Summenbildung der Kennzahl einfließen zu lassen, wird ein berechnetes Feld erstellt, welches die Granularität berücksichtigt.

Planwerte LoD
Abbildung 13: Berechnetes Feld für Planwerte LoD

Extrakte

Für alle beschriebenen Modellierungsvarianten wurden neben der Verwendung von Live- Verbindungen zu den csv_Dateien auch Extrakte erstellt und ausgewertet. Bei der Erstellung der Extrakte kann festgelegt werden, ob die Extrakt-Tabellen auf Basis der logischen oder physischen Tabellen im Datenmodell erstellt werden sollen.

Daten extrahieren
Abbildung 14: Extrakteinstellungen

Im Beispiel der Cross Join-Variante würde ein Extrakt als logische Tabelle erst alle Dimensionen miteinander verknüpfen und anschließend als eine flache Extrakt-Tabelle speichern, während der Extrakt als physische Tabelle alle Dimensionstabellen als eigene Tabellen speichert. Die Faktentabellen werden in beiden Fällen separat erstellt.

Für die Auswertung wurden beide Auswahlmöglichkeiten getestet. Lediglich für die Variante All_Dim (im Vorfeld durchgeführter Cross Join) ist bei der Erstellung des Extrakts nur die Speicherung als logische Tabellen möglich, da keine physischen Verknüpfungen innerhalb der logischen Tabellen durchgeführt werden.

Hieraus resultieren somit in Summe acht getestete Tableau Datenquellen:

Modell

Verbindung

Cross Join

(in einer logischen Tabelle)

 

Live

Extrakt (als physische Tabellen, phy)

Extrakt (als logische Tabellen, log)

All_Dim

(vorab gebildeter Join aller Dimensionen)

Live

Extrakt (als logische Tabellen, log)

LoD

Live

Extrakt (als physische Tabellen, phy)

Extrakt (als logische Tabellen, log)

Tests / Ergebnisse

Als einheitlicher Testfall wurde für jede Datenquelle die gleiche Visualisierung erstellt und die Performance mittels Leistungsaufzeichnung über mehrere Zyklen erfasst. Der Cache wurde hierbei nach jedem Durchlauf geleert. Um sicherzustellen, dass in der Abfrage stets alle Tabellen im jeweiligen Modell abgefragt werden, wurden für den Testfall alle Hierarchien aus den Dimensionstabellen und die Kennzahlen aus den Faktentabellen verwendet.

Testfall
Abbildung 15: Testfall

Im Fokus der Auswertung liegt vor allem die durchschnittliche Gesamtdauer aller Execution Queries (also die Zeit, die Tableau auf die Ausführung des Daten-SQLs wartet). Grundsätzlich lässt sich festhalten, dass Tableau für den Testfall drei Execution Queries generiert (jeweils eine für Ist- Kennzahl Berechnung, Plan-Kennzahl Berechnung und alle Dimensionen). Eine Ausnahme stellt hierbei das LoD Modell dar, welches zur Bestimmung aller Inhalte lediglich eine Query benötigt.

Test-Queries
Abbildung 16: Test-Queries in [s]
  1. Extrakte bilden führt nicht zwangsläufig zu verkürzten Execution Queries

Mit Blick auf die durchschnittliche Gesamtdauer der Execution Queries über alle Testfälle zeigt sich, dass die Erstellung eines Extraktes nicht gleichbedeutend mit verkürzten Execution Queries sein muss: In den Modellierungen ‚Cross Join‘ und ‚All_Dim‘ können sogar bei Speicherung auf logischen Tabellen im Vergleich zur Live-Verbindung längere Execution Times festgestellt werden.

  1. Performance ist nicht mit Execution Time gleichzusetzen

Ein anderer wichtiger Aspekt hierbei ist, dass Tableau bei jeder Abfrage das passende SQL Statement generiert (Compile Queries). Insbesondere bei den letztgenannten Live-Modellen ist aufgefallen, dass die Compile Queries die Execution Queries weit überschritten (die Compile Queries sind in Abbildung 16 vernachlässigt, um andere Größen besser vergleichen zu können). Um ein verlängertes Laden beim initialen Öffnen einer Arbeitsmappe oder beim Aktualisieren der Datenquelle mit vergleichbarem Datensatz zu vermeiden, kann die Verwendung eines Extraktes somit auch in vermeintlich längeren Varianten sinnvoll und hilfreich sein. Bei der Modellierung mit LoDs kann eine leichte Verkürzung der Execution Query durch die Verwendung beider Extraktvarianten ermittelt werden.

  1. csv-Live Verbindungen sind im Testfall gleich schnell

Generell ist im Bereich der Live-Verbindungen hinsichtlich der durchschnittlichen Execution Query-Gesamtdauer kein wesentlicher Unterschied zwischen den unterschiedlichen Modellierungen feststellbar (~35s). Wobei hier fairerweise festzuhalten ist, dass das Reporting auf csv-Dateien dieser Größe grundsätzlich nicht performant sein kann und hier relationale, indexbasierte Datenbanken sich anders geben können.

  1. Schnellste Verarbeitung mit Cross Join im physischen Layer und Extrakt auf physischen Tabellen

Im Gesamtvergleich stellt sich eine Modellierungsform für den durchgeführten Testfall als besonders performant dar: Das Bilden eines Cross Joins aller Dimensionstabellen innerhalb einer logischen Tabelle einschließlich der Speicherung des Extrakts auf physische Tabellen. Das heißt, alle Dimensionen werden innerhalb des Extrakts als separate Tabelle gespeichert und erst in den Abfragen miteinander verknüpft. Auch der Blick im Vergleich auf die Werte von ‚All_Dim Extract (log)‘ und ‚Cross Extract (log)‘ lässt darauf schließen, dass Tableaus Hyper Engine schnellere Abfragen durchführt, wenn die Dimensionstabellen separat voneinander gespeichert sind, anstatt vorab in einer großen Tabelle zusammengeführt werden.

Schaut man sich nun einen Vergleich der Live-Version und des besonders performanten Extrakts nach den einzelnen Execution Queries an (wie oben beschrieben werden drei generiert), lässt sich erkennen, dass die Dauer der Kennzahlenberechnungen im Schnitt kaum voneinander abweicht.

Cross Join Execution Queries im Vergleich
Abbildung 17: Cross Join Execution Queries im Vergleich

Jedoch führt der auf physische Tabellen verteilte Extrakt dazu, dass alle im Testfall verwendeten Dimensionen wesentlich schneller abgefragt werden können und somit daraus ein immenser Performance-Gewinn resultiert.

Zusammenfassung / Empfehlung

In Tableaus 2020.2 Version releastem neuen Relationen-Modell stellt es sich häufig als herausfordernd dar, eine Datenquelle zu bauen, die mehrere Faktentabellen enthält, die sich dieselben Dimensionstabellen teilen (Multiple Factsheets with shared Dimensions). Als Lösungsansatz wurde hierbei eine logische Tabelle verwendet, die alle Dimensionsausprägungen durch einen physischen Cross Join enthält und mit den Faktentabellen logisch verknüpft wurde.

Im Rahmen von einem definierten Testfall konnte gezeigt werden, dass die Modellierung, in der alle Dimensionstabellen separat voneinander vorliegen und erst in Tableau miteinander gejoint werden, die schnellsten Abfragezeiten erzielen konnte. Als Vergleich wurde hierbei eine Variante analysiert, die den Cross Join aller Dimensionen vorab berechnet hatte (als eine große Gesamttabelle) sowie eine klassische Modellierung mit Hilfe von LoDs.

Im Zusammenhang mit der Verwendung eines Extrakts, der die Tabellen auf physische Tabellen speichert, konnte gezeigt werden, dass es für Tabeaus Hyper Engine vorteilhaft ist, erst in der Abfrage mehrere Tabellen miteinander zu joinen als eine große, flache Tabelle einzulesen, die bereits alle Ausprägungen enthält.

Auf Basis des Testfalls ist somit für das Modell mit mehreren Faktentabellen, die mit denselben Dimensionstabellen verknüpft werden sollen, zu empfehlen, die Dimensionstabellen separat voneinander zu speichern und erst in Tableau miteinander zu joinen. Dieser Cross Join definiert im Relationen-Modell eine logische Tabelle, die unter Berücksichtigung der Kardinalität mit den Faktentabellen verbunden und dann in einen Extrakt überführt werden kann.

Modellierungsempfehlung
Abbildung 18: Modellierungsempfehlung

Quellen:

[1] https://help.tableau.com/current/pro/desktop/en-us/relate_tables.htm
[2] https://help.tableau.com/current/pro/desktop/en-us/relate_tables.htm
[3] https://help.tableau.com/current/pro/desktop/en-us/datasource_datamodel.htm
[4] https://help.tableau.com/current/online/de-de/datasource_datamodel.htm

Teile diesen Artikel mit anderen

Über den Autor

Philipp ist seit November 2019 als BI Consultant bei Woodmark tätig. Im Rahmen seiner Kundenprojekte beschäftigt er sich schwerpunktmäßig mit der Aufbereitung sowie mit der anschließenden Visualisierung und Analyse von Daten. Darüber hinaus schult Philipp in Basic und Advanced Trainings den Umgang mit Tableau.

Zur Übersicht Blogbeiträge