Skalierbares Data Warehouse: Data Vault Hubs mit dbt und Metadaten automatisieren
Moderne Unternehmen benötigen Data-Warehouse-Architekturen, die nicht nur robust, sondern vor allem anpassungsfähig sind. Wenn sich Quellsysteme ändern oder neue Geschäftsanforderungen entstehen, darf das Data Warehouse kein Engpass sein.
Genau hier setzt Data Vault 2.0 an. Als De-facto-Standard für Enterprise Data Warehousing bietet es durch die strikte Trennung von Geschäftsschlüsseln (Hubs), Beziehungen (Links) und Kontextdaten (Satellites) eine enorme Flexibilität und Auditierbarkeit.
Doch dieser architektonische Vorteil hat einen Preis: Komplexität. Ein vollständig modelliertes Data Vault besteht schnell aus Hunderten, wenn nicht Tausenden von Einzelobjekten. Die manuelle Entwicklung dieser Strukturen ist nicht nur zeitaufwendig, sondern auch extrem fehleranfällig für „Copy-Paste“-Fehler. Um Data Vault im großen Maßstab effizient zu betreiben, ist eine Automatisierung der Code-Generierung kein Luxus, sondern eine Notwendigkeit.
In diesem Beitrag zeigen wir einen technisch eleganten Weg, wie sich diese standardisierten Strukturen mithilfe von dbt (data build tool), Jinja-Templating und Metadaten effizient und fehlerfrei generieren lassen. Hierbei dient dbt als Tool für die Daten-Pipeline und Jinja als Skriptsprache für die Automatisierung, während YAML das Dateiformat ist, in dem alle Informationen gespeichert werden.
Technische Grundlage: Zugriff auf YAML-Metadaten
Im Kompilier- und Ausführungszeitraum stellt dbt das graph-Objekt zur Verfügung. Dieses Objekt enthält den vollständigen Kontext des Projekts, einschließlich aller Konfigurationen, die in schema.yml oder sources.yml definiert sind. Dieses Objekt enthält den vollständigen Kontext des Projekts, einschließlich aller Konfigurationen, die in schema.yml oder sources.yml definiert sind.
Anstatt SQL-Logik hardcodiert in Modellen abzulegen, wird die Logik in generische Makros ausgelagert. Das Modell selbst ruft nur noch die Konfiguration ab.
Funktionsweise:
Implementierungsbeispiel: Automatisierung eines Hubs
Im Folgenden wird dargestellt, wie ein Hub ohne manuellen SQL-Aufwand erstellt wird.
models: - name: raw_customers columns: - name: customer_id meta: is_business_key: true - name: load_date meta: is_load_date: true
{% macro generate_hub(source_model) %} {% if execute %} {# Zugriff auf die Node-Konfiguration im Graph #} {% set nodes = graph.nodes.values() | selectattr('name', 'equalto', source_model) | first %} {% set business_key = "" %} {# Iteration durch Spalten zur Findung des Business Keys #} {% for col_name, info in nodes.columns.items() %} {% if info.meta.get('is_business_key') %} {% set business_key = col_name %} {% endif %} {% endfor %} {# Ausgabe des standardisierten SQLs #} SELECT DISTINCT {{ dbt_utils.generate_surrogate_key([business_key]) }} as hub_hash_key, {{ business_key }}, current_timestamp as load_ts, '{{ source_model }}' as record_source FROM {{ ref(source_model) }} {% endif %} {% endmacro %}
Hinweis: In der Praxis greifen viele Teams auf etablierte Pakete wie AutomateDV zurück. Dieser Artikel dient dazu, das technische Verständnis zu schärfen und zu zeigen, wie man solche Automatisierungen ‚unter der Haube‘ mit Jinja und dbt-Metadaten selbst implementieren kann, wenn man volle Kontrolle benötigt.
{{ generate_hub('raw_customers') }}
Vorteile gegenüber manueller Entwicklung
Der Einsatz dieses Patterns bietet gegenüber dem manuellen Schreiben von SQL-Dateien messbare Vorteile in der Entwicklung und Wartung:
Voraussetzung: Das Paket dbt-utils muss in der packages.yml installiert sein, um die Hashing-Funktion nutzen zu können.