← Danny TobischProjekt 01

Datenarchitektur · Referenzaufbau

Eine Zahl,
drei Antworten.

Drei Abteilungen beantworten dieselbe Frage und legen drei verschiedene Zahlen vor. Niemand hat sich verrechnet. Das ist kein Rechenproblem, sondern ein Architekturproblem — und die Lösung dafür heißt seit dreißig Jahren im Kern gleich, auch wenn die Werkzeuge jedes Jahr neue Namen bekommen.

4 interaktive Ansichten durchgehendes Beispiel inklusive der Grenzen

01 — Das Problem

Wie viele aktive Abos hatten wir im Juli?

Diese Frage begleitet die ganze Seite. Sie klingt trivial, und in einem Unternehmen mit einem Abo-Produkt bekommt man auf sie regelmäßig drei verschiedene Zahlen.

Marketing

12.480

Zählt jeden, der im Juli ein gültiges Abo hatte — auch wenn er am 3. Juli gekündigt hat und am 31. Juli nicht mehr da war.

Finance

11.905

Zählt nur, wer am Monatsletzten zahlend war. Gekündigte in der Restlaufzeit zählen nicht mit, Testphasen auch nicht.

Product

10.212

Zählt nur, wer sich im Juli tatsächlich eingeloggt hat. Wer zahlt, aber nicht nutzt, ist für Product nicht aktiv.

Alle drei Zahlen sind richtig. Keine der drei Abteilungen hat sich verrechnet. Sie beantworten drei verschiedene Fragen, die zufällig denselben Namen tragen — und keine von ihnen hat je aufgeschrieben, welche.

Das ist kein Rechenproblem. Es ist ein Definitionsproblem, und Definitionen brauchen einen Ort, an dem sie stehen.

Genau dafür gibt es die Schichten, um die es im Folgenden geht. Sie sind keine Bürokratie und keine Mode. Sie sind der Ort, an dem aus Daten ein Begriff wird — und der Grund, warum die Frage am Ende genau eine Antwort hat.

Was hier steht und was nicht

Diese Seite beschreibt ein Referenzmuster, keine konkrete Installation. Alle Zahlen, Tabellennamen und Beispiele sind erfunden. Die Werkzeuge — dlt, BigQuery, dbt, Metabase, Terraform — sind austauschbar; das Muster funktioniert genauso mit Airbyte, Snowflake, SQLMesh oder Superset.

Was nicht austauschbar ist, sind die Regeln zwischen den Schichten. Um die geht es.

02 — Der Aufbau

Vertrauen wächst nach oben

Ein Data Warehouse hat Schichten aus demselben Grund, aus dem ein Wasserwerk Filter hat: Man will an einer Stelle wissen, wie sauber das ist, was herauskommt. Jede Schicht hat genau eine Aufgabe und genau eine Regel darüber, was sie nicht tun darf.

Interaktiv

Klick auf eine Schicht: Was steht dort, wer darf sie abfragen, und wie sieht unser Beispiel dort aus?

Die eine Regel

Jede Schicht liest nur aus der Schicht direkt darunter. Kein Datamart greift auf Bronze zu, kein Dashboard auf Silver. Wer diese Regel bricht, spart einmal eine Stunde und zahlt sie ein Jahr lang zurück.

Der Preis dafür ist Redundanz: Dieselbe Information liegt in vier Formen herum. Das ist Absicht. Speicher ist billig, Rekonstruktion ist teuer, und eine Schicht, die man jederzeit neu bauen kann, ohne das Quellsystem zu fragen, ist die eigentliche Versicherung.

03 — Die Ladung

Erst laden, dann denken

Die klassische Reihenfolge hieß ETL: extrahieren, transformieren, laden. Transformiert wurde unterwegs, im Ladeprozess. Heute lädt man zuerst und transformiert danach — ELT — und der Grund dafür ist weniger technisch als organisatorisch.

ETL, alte Ordnung

Transformation unterwegs

Was der Ladeprozess wegwirft, ist weg. Ein Denkfehler in der Logik von 2023 lässt sich 2026 nicht mehr reparieren — die Rohdaten wurden nie gespeichert.

ELT, heutige Ordnung

Transformation im Lager

Das Rohmaterial bleibt liegen. Stellt sich eine Logik als falsch heraus, baut man die Schichten darüber neu — ohne das Quellsystem noch einmal zu belasten.

In diesem Aufbau übernimmt dlt das Laden. Es ist eine Python-Bibliothek, kein Dienst: Man schreibt eine Funktion, die Datensätze liefert, und dlt kümmert sich um den Rest — Zieltabelle anlegen, Typen ableiten, neue Felder ergänzen, Ladestand merken.

Beladung einer Quelle
# Die Quelle liefert Datensätze. Mehr muss sie nicht wissen.
@dlt.resource(name="abos", write_disposition="merge", primary_key="id")
def abos(aktualisiert_ab=dlt.sources.incremental("updated_at")):
    yield from api.hole_seiten("/subscriptions", seit=aktualisiert_ab.last_value)

pipeline = dlt.pipeline(destination="bigquery", dataset_name="bronze_billing")
pipeline.run(abos)

Was dabei zählt

Inkrementell

Nur das Neue

Ein Zeitstempel oder eine laufende Nummer merkt sich, wo der letzte Lauf aufgehört hat. Vollladungen sind ein Notfallwerkzeug, kein Tagesgeschäft.

Idempotent

Zweimal laden schadet nicht

Läuft ein Job doppelt, muss dasselbe herauskommen. Über einen Schlüssel und merge statt append ist das geschenkt.

Schema-Evolution

Neue Felder brechen nichts

Fügt die Quelle eine Spalte hinzu, wird sie angelegt. Ändert sie einen Typ, gibt es eine Warnung statt eines stillen Datenverlusts.

Der Fehler, den man einmal macht

Verlockend ist, schon beim Laden „nur das Nötige“ zu holen und dabei aufzuräumen — Felder weglassen, Werte umbenennen, Zeilen filtern. Sechs Monate später fragt jemand nach genau diesen Feldern.

Die Ladung hat eine einzige Aufgabe: vollständig und unverändert ankommen. Alles Weitere passiert danach, wo man es zurücknehmen kann.

04 — Vier Stationen

Wie aus einer Zeile ein Begriff wird

Die gängigste Benennung dafür ist die Medaillon-Architektur: Bronze, Silver, Gold — darüber die Datamarts und das Reporting. Die Namen sind Etiketten für drei Vorgänge, die man auseinanderhalten sollte: aufräumen, verstehen, zuschneiden. Jede Schicht macht genau eines davon.

SchichtAufgabeDarfDarf nicht
Bronze Aufbewahren Genau das speichern, was kam — plus Ladezeitpunkt und Quelle. Irgendetwas ändern. Von Menschen abgefragt werden.
Silver Aufräumen Umbenennen, typisieren, entdoppeln, offensichtlichen Müll filtern. Ein Modell pro Quelltabelle. Joinen. Geschäftslogik enthalten. Aggregieren.
Gold Verstehen Quellen zusammenführen, Begriffe definieren, Historie führen. Dimensional modelliert. Auf eine einzelne Abteilung zugeschnitten sein.
Datamarts Zuschneiden Breit, flach, sprechend benannt. Eine Abteilung, ein Themenbereich. Neue Begriffe erfinden, die es in Gold nicht gibt.
Reporting Ausliefern Dashboards, automatische Berichte, Sprachmodellzugriff. Lesend. Rechnen. Joinen. Begriffe erfinden.

Interaktiv

Dieselbe Frage, vier Schichten. Klick dich durch und sieh, wie die Abfrage von unten nach oben kürzer und verständlicher wird — und wo die Arbeit dafür hingewandert ist.

Was dbt dabei tut

Jedes Modell ist eine Datei mit einem SELECT darin. Referenzen laufen nicht über Tabellennamen, sondern über ref() — daraus leitet dbt selbst ab, in welcher Reihenfolge gebaut werden muss, und zeichnet nebenbei den Abhängigkeitsgraphen.

models/gold/dim_kunde.sql
select
  k.kunde_id,
  k.email_domain,
  t.tarif_name,
  k.gueltig_ab,
  k.gueltig_bis,
  k.ist_aktuell
from {{ ref('stg_billing__kunden') }} as k
left join {{ ref('stg_billing__tarife') }} as t
  on k.tarif_id = t.tarif_id

Dazu kommen Tests als Teil des Modells, nicht als nachgelagerte Übung. Ein Test ist eine Behauptung über die Daten, die bei jedem Lauf geprüft wird.

models/gold/schema.yml
models:
  - name: dim_kunde
    columns:
      - name: kunde_id
        tests: [not_null]
      - name: ist_aktuell
        tests:
          - accepted_values: { values: [true, false] }
    # genau eine aktuelle Zeile pro Kunde
    tests:
      - unique_combination: { columns: [kunde_id, ist_aktuell], where: "ist_aktuell" }

Faustregel

Ein Test ist billig zu schreiben und teuer zu vermissen. Die zwei, die sich immer lohnen: Der Schlüssel ist eindeutig und der Schlüssel ist nicht leer. Fast jeder stille Datenfehler, der es bis ins Dashboard schafft, verletzt einen von beiden.

05 — Der Kern

Dimensional modellieren

Die Form, die Ralph Kimball in den Neunzigern beschrieben hat, hat seitdem niemand ernsthaft verbessert: Fakten in der Mitte, Dimensionen außen herum. Ein Stern.

Sternschema

In der Mitte, was passiert ist. Außen herum, worüber man es aufschlüsseln möchte.

fct_abo_ereignis eine Zeile = ein Ereignis mrr_betrag · anzahl dim_kunde Segment · Land · Tarif dim_tarif Name · Preis · Stufe dim_datum Monat · Quartal · Woche dim_kanal Quelle · Kampagne Fakten sind zahlreich und schmal · Dimensionen sind wenige und breit

Der wichtigste Satz eines Faktenmodells

„Eine Zeile in dieser Tabelle ist …“

Dieser Satz heißt Grain — die Körnung. Er wird zuerst festgelegt, vor jeder Spalte, und er wird aufgeschrieben. Ist der Grain unklar, addieren sich Kennzahlen falsch, und niemand merkt es, weil das Ergebnis plausibel aussieht.

In unserem Beispiel: Eine Zeile ist ein Ereignis im Lebenslauf eines Abos — Abschluss, Tarifwechsel, Kündigung, Reaktivierung. Nicht „ein Abo“, nicht „ein Kunde pro Monat“. Aus dieser Wahl folgt alles andere.

Und die Zeit

Ein Kunde wechselt im Mai von Basis auf Premium. Fragt man im Juli „wie viele Premium-Kunden hatten wir im Januar“, lautet die richtige Antwort: er war im Januar keiner. Eine Dimension, die nur den heutigen Stand kennt, kann das nicht beantworten.

Interaktiv

Ein Kunde, drei Tarifwechsel. Schieb den Stichtag und vergleiche, was eine überschreibende Dimension (Typ 1) und eine historisierende (Typ 2) antworten.

Slowly Changing Dimension, Typ 2

Statt die Zeile zu überschreiben, wird die alte geschlossen und eine neue geöffnet. Jede Zeile trägt gueltig_ab, gueltig_bis und ein Kennzeichen ist_aktuell. Der Fakt zeigt auf die Version, die zum Zeitpunkt des Ereignisses galt — nicht auf die heutige.

Nicht alles braucht Historie

Typ 2 kostet Komplexität: mehr Zeilen, kniffligere Joins, ein Schlüssel, der nicht mehr der fachliche ist. Für eine Tippfehlerkorrektur im Kundennamen ist das Unsinn — dort überschreibt man (Typ 1) und gut.

Die Frage lautet nicht „historisieren wir?“, sondern: Wird jemand diese Eigenschaft je rückwirkend auswerten wollen? Bei Tarif, Segment und Land lautet die Antwort ja. Bei der Schreibweise des Vornamens nicht.

06 — Die Auflösung

Eine Definition, ein Ort

Zurück zu den drei Zahlen vom Anfang. Die Lösung ist nicht, sich auf eine zu einigen — alle drei werden gebraucht. Die Lösung ist, ihnen drei verschiedene Namen zu geben und jeden davon genau einmal zu definieren.

NameDefinitionWer fragt danach
abos_im_zeitraum Abos, die zu irgendeinem Zeitpunkt im Zeitraum gültig waren. Marketing, Reichweite
zahlende_abos_stichtag Abos, die am Stichtag zahlend waren. Ohne Testphasen, ohne gekündigte in Restlaufzeit. Finance, Umsatz
genutzte_abos_im_zeitraum Abos mit mindestens einer Anmeldung im Zeitraum. Product, Bindung

Sobald jede Kennzahl einen eindeutigen Namen hat, verschwindet der Streit. Er wird ersetzt durch eine sehr viel bessere Frage: Welche der drei meinst du?

Und wo steht die Definition?

Nicht im Dashboard, und das ist der ganze Punkt. Eine Formel, die in einem BI-Werkzeug eingetippt wurde, ist nicht versioniert, nicht getestet, nicht auffindbar und existiert am Ende so oft, wie es Dashboards gibt.

models/gold/fct_abo_monat.sql — die Definition selbst
select
  monat,
  count(distinct case when gueltig_im_monat  then abo_id end) as abos_im_zeitraum,
  count(distinct case when zahlend_am_letzten then abo_id end) as zahlende_abos_stichtag,
  count(distinct case when hat_anmeldung     then abo_id end) as genutzte_abos_im_zeitraum
from {{ ref('int_abo_monat_status') }}
group by monat
Wenn die Definition an einer Stelle steht, ist eine Änderung eine Zeile Code und ein Testlauf. Steht sie an vierzig Stellen, ist sie ein Projekt.

Wer weiter gehen will, legt eine semantische Schicht darüber: Metriken, Dimensionen und erlaubte Verknüpfungen als Metadaten, aus denen die Abfrage erzeugt wird. Das lohnt sich ab einer gewissen Größe — und wird im vorletzten Kapitel noch einmal wichtig, wenn ein Sprachmodell die Fragen stellt.

07 — Die Oberfläche

Was das BI-Werkzeug darf

Metabase steht hier stellvertretend für jedes BI-Werkzeug. Die interessante Frage ist nicht, welches man nimmt, sondern wie viel Logik man hineinlässt.

darf

Fragen, filtern, zeigen

Auf Datamarts zugreifen, nach Zeitraum und Dimension filtern, gruppieren, darstellen, teilen. Genau dafür ist es gebaut.

mit Bedacht

Einfache Ableitungen

Anteile, Differenzen zum Vormonat, Sortierungen. Solange die Größen darunter definiert sind und die Rechnung eine Zeile ist.

darf nicht

Begriffe erfinden

Joins über mehrere Datamarts, Filter, die eine Geschäftsregel kodieren, neue Kennzahlen. Das gehört ins Modell, wo es getestet und gefunden werden kann.

Der Prüfstein

Wenn jemand fragt „woher kommt diese Zahl?“ — kann man ihm eine Datei im Git zeigen? Wenn die Antwort lautet „das hat jemand mal ins Dashboard getippt“, gehört die Logik eine Schicht tiefer.

Was gut funktioniert

Datamarts breit und sprechend zu bauen, damit die Oberfläche nichts mehr tun muss. ist_gekuendigt statt status_id = 7. monat_beginn als fertige Spalte statt einer Datumsfunktion im Dashboard. Jede Verrenkung, die ein Nutzer im BI-Werkzeug macht, ist ein Hinweis auf eine fehlende Spalte im Datamart.

Und: Rechte auf Datensätze, nicht auf Dashboards. Wer nur seine Region sehen darf, soll das über eine Zeilenfilterregel bekommen, nicht dadurch, dass man ihm bestimmte Kacheln vorenthält.

08 — Der Automat

Berichte, die von selbst kommen

Die meisten Fragen an ein Data Warehouse sind wiederkehrend. Dafür braucht niemand ein Dashboard zu öffnen — es reicht, wenn die Antwort erscheint.

Abonnement

Regelmäßig

Montags um sieben der Wochenbericht in den Posteingang oder den Team-Kanal. Nützlich, solange jemand widerspricht, wenn eine Zahl komisch aussieht.

Schwelle

Nur bei Auffälligkeit

Meldung, wenn die Kündigungsquote über einen Wert steigt oder eine Ladung ausbleibt. Deutlich wertvoller als der tägliche Bericht, den keiner liest.

Frische

Sind die Daten aktuell?

Ein Test auf das Alter der jüngsten Zeile. Schlägt er an, ist der Bericht falsch, bevor ihn jemand liest — und man erfährt es vorher.

Der unangenehme Teil

Berichte vermehren sich und sterben nie. Nach zwei Jahren laufen sechzig Stück, von denen ein Drittel niemand mehr öffnet — sie kosten trotzdem Rechenzeit, erzeugen trotzdem Warnungen und müssen trotzdem gepflegt werden.

Die meisten BI-Werkzeuge protokollieren, welche Frage wie oft aufgerufen wurde. Dieses Protokoll ist selbst eine Datenquelle. Einmal im Quartal auswerten und abschalten, was seit sechs Monaten niemand angesehen hat — das ist die undankbarste und lohnendste halbe Stunde im Jahr.

09 — Der Zugang

Mit den Daten sprechen

Die Vorstellung ist verlockend und mittlerweile technisch erreichbar: Jemand fragt in normaler Sprache, ein Sprachmodell schreibt die Abfrage, die Antwort kommt zurück. Kein Ticket, kein Dashboard, keine Wartezeit.

Das funktioniert — aber nur oberhalb einer bestimmten Schicht. Und der Grund dafür ist genau derselbe, aus dem es die Schichten überhaupt gibt.

Interaktiv

Dieselbe Frage, an zwei verschiedene Schichten gerichtet. Wähle, worauf das Modell zugreifen darf.

Warum es auf Bronze scheitert

Nicht, weil das Modell zu dumm wäre. Sondern weil die Information, die es bräuchte, dort schlicht nicht steht.

Namen

sind kryptisch

sub_st, flg_act, dt_c. Das Modell rät. Manchmal rät es richtig.

Auswahl

ist mehrdeutig

Fünf Tabellen enthalten etwas, das „Kunde“ heißen könnte. Drei davon sind veraltet, eine ist ein Testimport.

Regeln

stehen nirgends

Dass Testphasen nicht als zahlend gelten, steht in keinem Schema. Es steht in einem Kopf oder in einem dbt-Modell.

Verknüpfungen

sind Fallen

Ein Join über den falschen Schlüssel vervielfacht Zeilen. Die Summe ist dann zu hoch — aber nicht so hoch, dass es auffällt.

Eine plausible falsche Zahl ist gefährlicher als eine Fehlermeldung. Fehlermeldungen werden bemerkt.

Was tatsächlich hilft

Die kürzeste Zusammenfassung: Ein Modell soll nicht raten, sondern nachschlagen. Alles Weitere folgt daraus.

1 — Auf einem Datamart ansetzen, nicht auf Bronze

Ein gut gebauter Datamart erledigt den größten Teil der Arbeit von allein: sprechende Spaltennamen, keine Mehrdeutigkeit, Geschäftsregeln bereits angewendet. Aus status_id = 7 ist ist_gekuendigt geworden — und das versteht ein Sprachmodell ohne Anleitung.

2 — Werkzeuge statt freiem SQL

Statt „hier ist die Datenbank, schreib eine Abfrage“ bekommt das Modell einzelne Funktionen: Schema nachschlagen, Kennzahlendefinition abrufen, Spaltenwerte auflisten, eine Abfrage ausführen. Ein MCP-Server ist genau dafür gebaut. Jeder Schritt ist damit prüfbar, statt dass am Ende ein Block SQL herausfällt, den niemand liest.

3 — Die Kennzahl nachschlagen lassen

Fragt jemand nach „aktiven Abos“, soll das Modell nicht selbst entscheiden, was das heißt. Es soll die Definition abrufen — und wenn es drei gibt, zurückfragen. Genau hier zahlt sich die Semantikschicht aus Kapitel 6 aus.

4 — Enge Grenzen ziehen

Ausschließlich lesender Zugriff über ein eigenes Dienstkonto. Nur auf Datamarts, nicht auf Gold. Ein Limit für das gescannte Datenvolumen und die Laufzeit — sonst erzeugt eine unglückliche Frage eine Rechnung. Und: das erzeugte SQL wird immer angezeigt, nicht nur das Ergebnis.

Wo die Grenze verläuft

Für Erkundung ist das hervorragend: Nachfragen, Aufschlüsselungen, „zeig mir das mal nach Kanal“. Genau die Fragen, für die früher ein Ticket geschrieben wurde und die eine Woche später beantwortet zurückkamen, obwohl sie zehn Minuten Arbeit waren.

Für Zahlen, die in einen Quartalsbericht wandern, gilt etwas anderes. Dort ist eine Kennzahl das Ergebnis eines geprüften Modells, nicht eines Gesprächs. Der Weg dahin führt über den umgekehrten Ablauf: Das Gespräch findet die Frage, das Modell beantwortet sie dauerhaft.

Der Reflex, dem man widerstehen sollte

Wenn ein Sprachmodell auf schlecht modellierten Daten schlechte Antworten gibt, ist die Versuchung groß, das mit einer längeren Anweisung zu reparieren — alle Sonderregeln in den Systemprompt schreiben.

Das ist dieselbe Verlegung von Logik an den falschen Ort wie eine Formel im Dashboard, nur schlechter: nicht versioniert, nicht getestet, und bei jeder Modellversion wieder anders wirksam. Wenn die Anweisung erklären muss, was eine Spalte bedeutet, gehört diese Erklärung ins Datenmodell.

10 — Der Unterbau

Was man nicht neu bauen kann, hat man nicht verstanden

Ein Data Warehouse besteht nicht nur aus Tabellen. Es besteht aus Datensätzen, Berechtigungen, Dienstkonten, Zeitplänen, Verbindungen und einer Handvoll Einstellungen, die irgendwann jemand in einer Weboberfläche geklickt hat.

Genau diese geklickten Einstellungen sind das Problem. Sie stehen nirgends, niemand weiß mehr warum, und bei einem Umzug fehlen sie.

infrastruktur/warehouse.tf
resource "google_bigquery_dataset" "mart_finance" {
  dataset_id  = "mart_finance"
  location    = "EU"
  description = "Datamart Finance. Lesend fuer die Gruppe finance-analysts."
}

# Der Lesezugriff steht hier — nicht in einem Klickpfad.
resource "google_bigquery_dataset_iam_member" "mart_finance_leser" {
  dataset_id = google_bigquery_dataset.mart_finance.dataset_id
  role       = "roles/bigquery.dataViewer"
  member     = "group:finance-analysts@beispiel.de"
}

Terraform

Die Umgebung

Datasets, Rollen, Dienstkonten, Zeitpläne. Eine zweite Umgebung zum Testen ist damit eine Kopie mit anderem Präfix statt eines Nachmittags Klickarbeit.

dbt

Die Modelle

Transformationen, Tests, Beschreibungen. Der Abhängigkeitsgraph fällt dabei ab, ohne dass ihn jemand pflegen muss.

Git und CI

Die Kontrolle

Jede Änderung als Pull Request, jeder Pull Request baut gegen eine Testumgebung und lässt die Tests laufen. Was rot ist, geht nicht live.

Die Probe

Könnte man das gesamte Warehouse in einem leeren Projekt neu aufbauen, allein aus dem, was im Git steht? Wenn nein: Die Lücke zwischen Repository und Wirklichkeit ist genau das Stück, das beim nächsten Ausfall fehlt.

11 — Die Kehrseite

Was bricht

Bis hierher klang alles nach einer Ordnung, die von selbst hält. Tut sie nicht. Die folgenden fünf Punkte kosten in der Praxis mehr Zeit als der ganze Aufbau.

1 — Die Rechnung

BigQuery berechnet nicht die Laufzeit, sondern das gescannte Datenvolumen. Ein Dashboard, das stündlich select * über eine große Faktentabelle legt, kostet mehr als das gesamte Team an Rechenzeit verbraucht. Partitionierung nach Datum und Clustering nach dem häufigsten Filter sind keine Feinarbeit, sondern die Grundeinstellung.

Das wirksamste Gegenmittel ist unspektakulär: Kostenkontrollen einrichten, bevor man sie braucht. Ein Limit pro Abfrage, ein Limit pro Nutzer und Tag, und ein Blick auf die teuersten Abfragen der Woche.

2 — Die Quelle ändert sich ohne Ankündigung

Ein Feld wird umbenannt, ein Statuswert kommt hinzu, ein API-Endpunkt liefert plötzlich Seiten statt einer Liste. Niemand sagt Bescheid, weil niemand weiß, dass jemand mitliest.

Deshalb: Tests auf akzeptierte Werte, nicht nur auf Nichtleere. Ein neuer Statuswert soll den Lauf rot färben, nicht stillschweigend in einer else-Kategorie verschwinden.

3 — Die Abkürzung

Irgendwann ist es dringend, und jemand baut einen Datamart direkt aus Bronze. Es funktioniert, es ist schnell, und es ist der Anfang vom Ende — denn ab dann gibt es zwei Wege zur selben Zahl, die auseinanderlaufen werden.

Nicht die erste Abkürzung ist das Problem, sondern die dreißigste. Und die dreißigste kommt nur, wenn die erste durchgeht.

4 — Der Aufwand lohnt sich nicht immer

Bei drei Quelltabellen und zwei Auswertungen ist diese Architektur Überbau. Vier Schichten für ein Modell, das man in einer Abfrage schreiben könnte, kosten mehr, als sie bringen.

Die Schwelle liegt ungefähr dort, wo mehr als eine Person dieselben Daten für mehr als einen Zweck nutzt. Vorher ist Disziplin billiger als Struktur. Nachher ist es umgekehrt — und der Übergang tut weh, weil man ihn immer zu spät bemerkt.

5 — Die Modelle veralten leiser als der Code

Eine kaputte Funktion fällt auf. Ein Datamart, dessen fachliche Annahme seit einem Jahr nicht mehr stimmt, fällt nicht auf — er liefert weiter Zahlen. Nur eben die falschen.

Dagegen hilft kein Werkzeug, sondern ein Termin: einmal im Quartal mit der Fachseite durch die Kennzahlendefinitionen gehen und fragen, ob sie noch das messen, was gemeint war.

Und trotzdem

Nichts davon spricht gegen den Aufbau. Es spricht dagegen, ihn für fertig zu halten. Ein Data Warehouse ist kein Projekt mit einem Abschlussdatum, sondern ein Ort, an dem laufend verhandelt wird, was ein Wort bedeutet.

Der Erfolg lässt sich an einer einzigen Frage messen — derselben wie am Anfang: Wenn drei Abteilungen nach den aktiven Abos im Juli fragen, bekommen sie dann dieselbe Zahl? Oder wenigstens drei Zahlen, die verschiedene Namen tragen und von denen jeder weiß, welche er meint?

12 — Quellen

Nachlesen

Der Klassiker zur dimensionalen Modellierung ist Ralph Kimball und Margy Ross, The Data Warehouse Toolkit. Er ist dreißig Jahre alt, redet von Werkzeugen, die es nicht mehr gibt, und ist trotzdem das Buch, aus dem Grain, Fakten, Dimensionen und die Typ-1/Typ-2-Unterscheidung stammen.

Zur heutigen Umsetzung: die Dokumentation von dbt — insbesondere die Abschnitte zu Modellierung und Tests — und die von dlt zu inkrementellem Laden und Schema-Evolution. Für BigQuery lohnt der Abschnitt zu Partitionierung und Clustering; er spart mehr Geld als jede andere halbe Stunde Lektüre.

Zum Zugriff durch Sprachmodelle: die Spezifikation des Model Context Protocol. Sie beschreibt das Muster, das im neunten Kapitel gemeint ist — Werkzeuge mit klarem Zuschnitt statt freiem Datenbankzugriff.

Weiterlesen

← Zurück zur Startseite © 2026 Danny Tobisch · Impressum