Diplom-Biologe | Senior IT-Consultant
|
SH |
Sascha Hess xenosystems.de - IT-Consulting & Data Management |
www.xenosystems.de |
|
|
STRATEGISCHE WISSENS-ROADMAP 2026 |
|
|
SQL Server |
|
|
BI & Governance |
|
|
Datenarchitektur |
|
|
Welche Datenhaltungsarchitektur wann — und wie beide zusammenwachsen |
WAS SIE IN DIESEM KIT ERHALTEN:
|
|
1 |
Entscheidungsmatrix 12 Kriterien — DWH, Data Lake oder Lakehouse für Ihren Anwendungsfall |
|
|
2 |
10 Architektur-Fallen Typische Fehler beim Aufbau beider Architekturen — mit Sofort-Korrekturen |
|
|
3 |
DWH-Modellierung in SQL Star Schema, Slowly Changing Dimensions und Fact-Tabellen — sofort einsetzbar |
|
|
4 |
Lakehouse-Muster Medaillon-Architektur, Delta-Format und dbt auf SQL Server und Azure Fabric |
|
|
5 |
30-Tage-Architekturplan Vom konzeptlosen Reporting zum strukturierten Datenfundament |
HAFTUNGSAUSSCHLUSS
Alle Skripte, Architekturempfehlungen und Entscheidungshilfen wurden sorgfältig erarbeitet. Da jede Systemlandschaft individuell ist, übernimmt der Autor keinerlei Haftung für Datenverlust, Systemausfälle, unerwartete Cloud-Kosten oder Projektmisserfolge. Validieren Sie alle Architekturentscheidungen anhand Ihrer konkreten Anforderungen und testen Sie Implementierungen zunächst in Nicht-Produktionsumgebungen.
KEINE ERGEBNISGARANTIE
Genannte Performance-Werte, Kostenschätzungen und Projektzeiträume sind Erfahrungswerte aus realen KMU-Umgebungen. Tatsächliche Ergebnisse hängen von Datenvolumen, Teamkompetenz, Systemlandschaft und verfügbarem Budget ab.
CLOUD-KOSTEN-HINWEIS
Cloud-Dienste wie Azure Synapse, Microsoft Fabric und Databricks werden nach Nutzung abgerechnet. Angaben zu Kostenstrukturen entsprechen dem Stand März 2026. Konfigurieren Sie Kostenalerts, bevor Sie Cloud-Dienste produktiv einsetzen.
VERSIONSHINWEIS
Die Inhalte beziehen sich auf SQL Server 2022/2025, Azure Synapse Analytics, Microsoft Fabric, Databricks Runtime 15+, dbt Core 1.8+ und Power BI, Stand März 2026.
URHEBERRECHT
Dieses Dokument ist für den persönlichen oder betriebsinternen Gebrauch des Käufers lizenziert. Weiterverkauf, Weitergabe an Dritte und öffentliche Veröffentlichung sind ohne schriftliche Genehmigung nicht gestattet.
Eine ausführliche Version dieses Haftungsausschlusses befindet sich am Ende dieses Dokuments.
01 Einleitung
Warum die falsche Architekturwahl Jahre kostet
02 Grundkonzepte
Data Warehouse, Data Lake und Lakehouse — Definitionen und Geschichte
03 Entscheidungsmatrix
12 Kriterien mit Bewertungsschema für jede Situation
04 Die 10 Architektur-Fallen
Typische Fehler beim Aufbau — mit Sofort-Korrekturen
05 Data Warehouse in der Praxis
Star Schema, SCD, Fact-Tabellen und Aggregations-Layer
06 Data Lake und Lakehouse
Medaillon-Architektur, Delta-Format, Partitionierung
07 dbt als gemeinsame Transformations-Schicht
Modelle, Tests und Dokumentation für DWH und Lakehouse
08 Moderne Hybridarchitekturen
Fabric, Synapse und das Ende der Entweder-oder-Entscheidung
09 Governance, Qualität und Kosten
Datenkatalog, Qualitätssicherung und Cloud-Kostensteuerung
10 30-Tage-Architekturplan
Vom konzeptlosen Reporting zum strukturierten Datenfundament
01
In mittelständischen Unternehmen entstehen Datenarchitekturen selten durch strategische Entscheidungen — sie entstehen durch Notlösungen unter Zeitdruck. Ein Controller baut ein Power-BI-Dashboard direkt auf der ERP-Produktivdatenbank. Eine IT-Abteilung schaufelt CSV-Exports in einen Azure Blob Storage und nennt das "Data Lake". Ein externes BI-Projekt liefert ein Data Warehouse, das drei Jahre später niemand mehr versteht, weil die Dokumentation fehlt und der Berater weg ist.
Das Ergebnis ist in fast jedem KMU dasselbe: mehrere Datenquellen mit teils widersprüchlichen Zahlen, Power BI Berichte die niemand vertraut, manuelle Excel-Konsolidierungen vor jedem Führungsmeeting und eine wachsende Angst vor Schemaänderungen, die "alles kaputtmachen könnten."
Die Wahl zwischen Data Warehouse und Data Lake ist keine technische Modeentscheidung. Sie bestimmt, wie Ihr Unternehmen in den nächsten fünf bis zehn Jahren mit Daten arbeiten kann.
→ Ein Data Warehouse ist strukturiert, kuratiert und optimiert für bekannte Abfragen. Es ist das richtige Werkzeug für stabile Reporting-Anforderungen, controllingseitige KPIs und regulatorische Berichtspflichten.
→ Ein Data Lake ist flexibel, rohstofforientiert und optimiert für Exploration. Er ist das richtige Werkzeug, wenn Datenformen und Analysebedarf sich schnell verändern oder wenn maschinelles Lernen und Ad-hoc-Analysen auf Rohdaten erforderlich sind.
→ Ein Lakehouse kombiniert beide Ansätze — mit strukturierten Tabellen auf flexiblem Dateispeicher. Es ist 2026 für viele KMU der pragmatischste Ansatz, weil es die Stärken beider Welten ohne deren schlimmste Nachteile vereint.
Keines dieser Muster ist universell richtig. Dieses Kit hilft Ihnen, die richtige Wahl für Ihre konkrete Situation zu treffen — und danach die Implementierung solide aufzubauen.
|
|
DER HÄUFIGSTE KMU-STARTFEHLER ■ 72 % der KMU-BI-Projekte beginnen ohne explizite Architekturentscheidung — das Werkzeug (Power BI, Azure, SQL Server) wird gewählt, bevor das Konzept steht. ■ Die häufigste Folge: Power BI greift direkt auf Produktivdatenbanken zu — keine Historisierung, keine Versionsierung, kein stabiles Fundament. ■ Die zweit-häufigste Folge: Ein "Data Lake" entsteht als unkuratierter Dateifriedhof — viele Daten, null Nutzbarkeit. |
02
Ein Data Warehouse ist eine zentrale, strukturierte Datenbank, die speziell für analytische Abfragen optimiert ist. Es entstand in den 1980er Jahren als Antwort auf das Problem, dass OLTP-Systeme (ERP, CRM) für komplexe Aggregationen und historische Analysen ungeeignet sind.
Kernprinzip: Schema on Write — die Struktur wird definiert, bevor Daten geladen werden. Daten werden bereinigt, transformiert und in ein definiertes Schema überführt, bevor sie im Warehouse landen.
Klassische Schichtenarchitektur:
→ Staging Layer: Rohdaten aus Quellsystemen, temporär, wenig bis keine Transformation.
→ Core Layer: Bereinigte, historisierte Daten in 3NF oder dimensionalem Modell.
→ Data Mart Layer: Aggregierte, themenspezifische Sichten für Controlling, Vertrieb, Produktion.
|
-- Klassische DWH-Schichtenstruktur in SQL Server CREATE SCHEMA stg; -- Staging: rohe Quelldaten, temporär CREATE SCHEMA core; -- Core: bereinigt, historisiert, 3NF oder Dimensional CREATE SCHEMA dm; -- Data Mart: aggregiert, themenspezifisch CREATE SCHEMA rpt; -- Reporting: Views für Power BI DirectQuery
-- Metadaten-Spalten: jede Core-Tabelle bekommt sie -- _src_system: aus welchem Quellsystem -- _load_date: wann geladen -- _valid_from: gültig ab (für SCD Typ 2) -- _valid_to: gültig bis (NULL = aktuell) -- _is_current: schneller Filter auf aktuellen Datensatz -- _row_hash: Änderungs-Erkennung ohne Feldvergleich |
Ein Data Lake speichert Daten in ihrer natürlichen, unkurierten Form — als Dateien in einem flexiblen Speicher (Azure Data Lake Storage, Amazon S3, HDFS). Struktur wird erst beim Lesen aufgezwungen, nicht beim Schreiben.
Kernprinzip: Schema on Read — Rohdaten werden ohne Transformation gespeichert. Verschiedene Abfragen können denselben Rohdaten verschiedene Schemas aufprägen.
Warum er entstand: Big Data in den 2010er Jahren — strukturierte DWH-Prozesse waren zu langsam und zu teuer für die Verarbeitung von Clickstreams, Sensordaten und Social-Media-Strömen.
Warum er oft scheitert: Ohne Governance wird ein Data Lake zum Data Swamp — unstrukturierte Daten ohne Kontext, Qualität oder Auffindbarkeit.
Das Lakehouse kombiniert die Flexibilität des Data Lake (offenes Dateiformat, günstiger Speicher) mit der Struktur und Zuverlässigkeit des Data Warehouse (ACID-Transaktionen, Schema-Enforcement, Versionierung).
Technische Grundlage: Tabellenformate wie Delta Lake, Apache Iceberg oder Apache Hudi liefern ACID-Semantik auf Dateispeicher.
|
Eigenschaft |
Data Warehouse |
Data Lake |
Lakehouse |
|
Schema |
On Write (starr) |
On Read (flexibel) |
On Write (flexibel anpassbar) |
|
ACID-Transaktionen |
Ja |
Nein |
Ja (Delta/Iceberg) |
|
Dateiformat |
Proprietär / Columnar |
Beliebig |
Offen (Parquet + Delta) |
|
Skalierung Compute |
Vertikal (teuer) |
Horizontal |
Horizontal (Cloud-native) |
|
Query Performance |
Sehr hoch |
Mittel |
Hoch (mit Optimierung) |
|
Rohdaten verfügbar? |
Nein |
Ja |
Ja |
|
BI-Tool-Kompatibilität |
Sehr hoch |
Mittel |
Sehr hoch (DirectLake) |
|
Einstiegskosten KMU |
Mittel |
Niedrig |
Mittel |
|
Betriebskomplexität |
Mittel |
Hoch |
Mittel–Hoch |
→ SQL Server On-Premise + DWH: Bewährt, kostengünstig, hohe Kontrolle. Richtig für KMU ohne Cloud-Strategie oder mit strengen Datenhaltungsanforderungen.
→ Microsoft Fabric: Unified Analytics Platform — Lakehouse, DWH, Power BI, dbt und Pipelines in einer lizenzierten Einheit. Für Microsoft-affine KMU mit vorhandener M365/Power BI Premium Lizenz der direkteste Weg zum modernen Lakehouse.
→ Azure Synapse + ADLS2: Flexibler, mehr Konfigurationsaufwand als Fabric, aber auch mehr Kontrolle. Für KMU mit bestehenden Azure-Investitionen und individuellen Anforderungen.
03
Bewerten Sie jedes Kriterium mit 1 (trifft nicht zu) bis 3 (trifft voll zu). Das Muster mit dem höchsten Score ist Ihr Ausgangspunkt — nicht zwingend die einzige Antwort.
|
# |
Kriterium |
DWH |
Data Lake |
Lakehouse |
|
1 |
Reporting-Anforderungen sind stabil und gut definiert |
3 |
0 |
1 |
|
2 |
Datenquellen sind strukturiert (ERP, CRM, SQL) |
3 |
0 |
2 |
|
3 |
Team hat starke SQL-Kompetenz, keine Spark/Python-Erfahrung |
3 |
0 |
1 |
|
4 |
Regulatorische Anforderungen erfordern strikte Datenhistorie und Audit |
3 |
0 |
2 |
|
5 |
Datenvolumen < 100 GB pro Tag, kein starkes Wachstum erwartet |
3 |
1 |
1 |
|
6 |
Unstrukturierte Daten (Logs, JSON, Bilder, Sensoren) sind relevant |
0 |
3 |
2 |
|
7 |
Maschinelles Lernen und Data Science auf Rohdaten erforderlich |
0 |
3 |
2 |
|
8 |
Datenvolumen > 1 TB, starkes Wachstum erwartet |
0 |
2 |
3 |
|
9 |
Schema ändert sich häufig — neue Quellen, neue Attribute |
0 |
3 |
2 |
|
10 |
Microsoft Fabric oder Power BI Premium bereits lizenziert |
1 |
0 |
3 |
|
11 |
Cloud-Budget vorhanden, On-Premise-Investitionen abgeschrieben |
0 |
1 |
3 |
|
12 |
Explorative Analysen und Ad-hoc-Abfragen dominieren |
0 |
2 |
3 |
|
|
AUSWERTUNG UND EMPFEHLUNG ■ DWH-Score deutlich höher (> 8 Punkte Abstand): Klassisches DWH auf SQL Server — solide, bewährt, für Ihr Team beherrschbar. ■ Data Lake-Score deutlich höher: Prüfen Sie ob ein Lakehouse nicht sinnvoller ist — ein reiner Data Lake ohne Governance wird zum Swamp. ■ Lakehouse-Score führt oder Scores liegen nah beieinander: Lakehouse-Ansatz (Medaillon-Architektur) — heute der pragmatischste Einstieg für KMU mit Wachstumsambitionen. ■ Alle Scores unter 10: Architekturanforderungen sind noch nicht klar genug — vor der Technologiewahl steht die Anforderungsanalyse. |
Wenn Power BI bereits im Einsatz ist und direkt auf Produktivdatenbanken zugreift, ist die pragmatischste erste Maßnahme eine einfache DWH-Schicht auf SQL Server — unabhängig von der langfristigen Architektur. Das verhindert Produktivbelastung und schafft ein stabiles Fundament.
|
-- Schnellster Weg aus dem Direkt-auf-ERP-Szenario: -- Tägliche Snapshot-Tabellen als einfachstes DWH-Fundament CREATE TABLE dwh.Snapshot_Umsatz_Taeglich ( SnapshotDatum DATE NOT NULL, ArtikelNr NVARCHAR(20) NOT NULL, KundenNr INT NOT NULL, Region NVARCHAR(50), Umsatz_Netto DECIMAL(18,2), Menge DECIMAL(18,4), _geladen_am DATETIME2 DEFAULT SYSUTCDATETIME(), CONSTRAINT PK_Snap_Umsatz PRIMARY KEY (SnapshotDatum, ArtikelNr, KundenNr) );
-- Power BI verbindet sich ausschließlich auf dwh.* — nie auf dbo.* direkt -- Ergebnis: ERP-Produktivlast geht auf null, Historisierung entsteht automatisch |
04
Ein Azure Blob Storage wird befüllt mit CSV-Exporten, JSON-Dumps und Excel-Dateien. Sechs Monate später weiß niemand mehr, was welche Datei enthält, welche Datei aktuell ist und welche Qualität die Daten haben. Der "Data Lake" ist ein Archiv ohne Katalog.
LÖSUNG:
✓ Jede Datei im Lake hat Pflicht-Metadaten: Quelle, Extraktion-Zeitpunkt, Schema-Version, Verantwortlicher.
✓ Ordnerstruktur nach Medaillon-Muster: bronze/silver/gold — keine freie Ablage.
✓ Datenkatalog von Anfang an: Azure Purview oder auch nur eine gepflegte SQL-Tabelle mit Datei-Inventar.
|
-- Datei-Inventar auch ohne Azure Purview: einfache Verwaltungstabelle CREATE TABLE lake.Datei_Inventar ( DateiID INT IDENTITY PRIMARY KEY, Pfad NVARCHAR(500) NOT NULL, -- z.B. bronze/erp/auftraege/2026/03/ Dateiname NVARCHAR(200) NOT NULL, Schicht NVARCHAR(10) NOT NULL, -- BRONZE / SILVER / GOLD Quellsystem NVARCHAR(50), Thema NVARCHAR(100), -- 'Auftraege', 'Kunden' Format NVARCHAR(20), -- CSV, JSON, PARQUET, DELTA Zeilenanzahl BIGINT, Groesse_MB DECIMAL(10,2), Extraktion_Von DATETIME2, Extraktion_Bis DATETIME2, Erstellt_Am DATETIME2 DEFAULT SYSUTCDATETIME(), Verantwortlich NVARCHAR(100), Qualitaet NVARCHAR(10) DEFAULT 'UNGEPRUEFT' -- OK / WARNUNG / FEHLER ); |
Ein Data Warehouse überschreibt täglich die aktuellen Werte. Ein Jahr später fragt der Controller: "Wie sah die Kundenbewertung von Müller GmbH im März letzten Jahres aus?" Die Antwort: unbekannt. Das DWH kennt nur den heutigen Zustand.
LÖSUNG:
✓ Slowly Changing Dimensions (SCD) Typ 2 für alle Dimensionen mit Historisierungsbedarf.
✓ Valid-From / Valid-To Felder in allen Dimensionstabellen — SQL Server Temporal Tables als elegante Alternative.
✓ Snapshot-Tabellen für Kennzahlen, die sich täglich ändern (Lagerbestand, offene Posten).
|
-- SCD Typ 2: vollständige Historisierung einer Kundendimension CREATE TABLE dm.Dim_Kunden ( KundenKey INT IDENTITY PRIMARY KEY, -- Surrogate Key KundenNr INT NOT NULL, -- Business Key (aus ERP) Name NVARCHAR(200), Region NVARCHAR(50), Umsatzklasse NVARCHAR(20), Zahlungsziel INT, -- SCD-Typ-2-Felder _valid_from DATE NOT NULL, _valid_to DATE NOT NULL DEFAULT '9999-12-31', _is_current BIT NOT NULL DEFAULT 1, _row_hash BINARY(32), -- SHA2_256 über alle inhaltlichen Felder _src_system NVARCHAR(20) DEFAULT 'ERP', _load_date DATETIME2 DEFAULT SYSUTCDATETIME() );
-- MERGE-basiertes SCD-Typ-2-Update: erkennt Änderungen via Row-Hash CREATE OR ALTER PROCEDURE dwh.SP_Aktualisiere_Dim_Kunden AS BEGIN SET NOCOUNT ON;
-- Schritt 1: Geänderte Records identifizieren (Row-Hash-Vergleich) UPDATE dm.Dim_Kunden SET _valid_to = CAST(GETDATE() AS DATE), _is_current = 0 WHERE _is_current = 1 AND EXISTS ( SELECT 1 FROM stg.Kunden s WHERE s.KundenNr = dm.Dim_Kunden.KundenNr AND HASHBYTES('SHA2_256', CONCAT(s.Name,'|',s.Region,'|',s.Umsatzklasse,'|', CAST(s.Zahlungsziel AS NVARCHAR)) ) <> dm.Dim_Kunden._row_hash );
-- Schritt 2: Neue Version für geänderte + völlig neue Records einfügen INSERT INTO dm.Dim_Kunden (KundenNr, Name, Region, Umsatzklasse, Zahlungsziel, _valid_from, _row_hash) SELECT s.KundenNr, s.Name, s.Region, s.Umsatzklasse, s.Zahlungsziel, CAST(GETDATE() AS DATE), HASHBYTES('SHA2_256', CONCAT(s.Name,'|',s.Region,'|',s.Umsatzklasse,'|', CAST(s.Zahlungsziel AS NVARCHAR))) FROM stg.Kunden s WHERE NOT EXISTS ( SELECT 1 FROM dm.Dim_Kunden d WHERE d.KundenNr = s.KundenNr AND d._is_current = 1 ); END |
Ein Data-Warehouse-Modell mit 40 Dimensionstabellen und einer Fact-Tabelle mit 35 Foreign Keys. Jede Abfrage benötigt 12 JOINs. Power BI ist langsam, Queries sind schwer wartbar, neue Entwickler brauchen Wochen zur Einarbeitung.
LÖSUNG:
✓ Faustregel: maximal 8–12 Dimensionen pro Fact-Tabelle in einem ersten Modell.
✓ Junk Dimensions für viele kleine Low-Cardinality-Attribute (Status, Flag, Kategorie).
✓ Degenerate Dimensions für Belegnummern direkt in der Fact-Tabelle — kein JOIN nötig.
|
-- Junk Dimension: viele kleine Flags zu einer Tabelle zusammengefasst CREATE TABLE dm.Dim_Auftrags_Flags ( FlagsKey INT IDENTITY PRIMARY KEY, AuftragsStatus NVARCHAR(20), -- NEU / BESTÄTIGT / GELIEFERT / ABGESCHLOSSEN Prioritaet NVARCHAR(10), -- NORMAL / HOCH / EILAUFTRAG Herkunftskanal NVARCHAR(20), -- ONLINE / TELEFON / AUSSENDIENST / EDI IstReklamation BIT, IstWiederholung BIT, -- Statt 5 separater Dimensionstabellen: eine Junk Dimension CONSTRAINT UQ_Flags UNIQUE (AuftragsStatus, Prioritaet, Herkunftskanal, IstReklamation, IstWiederholung) );
-- Fact-Tabelle: kompakt, wenige JOINs CREATE TABLE dm.Fact_Auftraege ( AuftragsKey INT IDENTITY PRIMARY KEY, -- Dimensionsreferenzen (Surrogate Keys) DatumKey INT NOT NULL, -- Dim_Datum KundenKey INT NOT NULL, -- Dim_Kunden (SCD Typ 2) ArtikelKey INT NOT NULL, -- Dim_Artikel VertreterKey INT NOT NULL, -- Dim_Mitarbeiter FlagsKey INT NOT NULL, -- Dim_Auftrags_Flags (Junk) -- Degenerate Dimension: Belegnummer direkt in Fact, kein JOIN AuftragsNr NVARCHAR(20) NOT NULL, -- Metriken (additive und semi-additive) Nettobetrag DECIMAL(18,2), Menge DECIMAL(18,4), Deckungsbeitrag DECIMAL(18,2), -- Nicht-additive Metrik: separat behandeln Lieferzeit_Tage INT, -- niemals summieren! -- Metadaten _load_date DATETIME2 DEFAULT SYSUTCDATETIME() ); |
Eine Fact-Tabelle speichert Datumsfelder als DATETIME. Power BI erzeugt automatisch eine Datumshierarchie — aber ohne Fiskaljahr, ohne Wochennummern nach ISO, ohne Feiertage und ohne KW-basierte Kennzahlen. Jeder Controller baut diese Logik in DAX nach — dreimal, inkonsistent.
LÖSUNG:
✓ Eine vollständige Datumsdimension ist Pflichtbestandteil jedes DWH — einmalig generiert, dauerhaft genutzt.
✓ Enthält alle kalendarischen und unternehmensspezifischen Attribute: Fiskaljahr, Quartale, ISO-KW, Feiertage, Arbeitstage.
✓ Power BI nutzt die Datumsdimension — keine eigene Datumsintelligenz in DAX bauen.
|
-- Vollständige Datumsdimension — einmal generieren, für immer nutzen DECLARE @Start DATE = '2020-01-01'; DECLARE @Ende DATE = '2030-12-31';
WITH Kalender AS ( SELECT @Start AS Datum UNION ALL SELECT DATEADD(DAY, 1, Datum) FROM Kalender WHERE Datum < @Ende ) INSERT INTO dm.Dim_Datum ( DatumKey, Datum, Jahr, Quartal, Monat, MonatName, KW_ISO, Tag, Wochentag, WochentagName, IstWochenende, IstFeiertag, Feiertagsname, FiskaljJahr, FiskalQuartal, -- anpassen: Fiskaljahr beginnt z.B. April IstArbeitstag, Jahrestag, MonatsBeginn, MonatsEnde ) SELECT CAST(FORMAT(Datum,'yyyyMMdd') AS INT) AS DatumKey, Datum, YEAR(Datum) AS Jahr, DATEPART(QUARTER, Datum) AS Quartal, MONTH(Datum) AS Monat, FORMAT(Datum,'MMMM','de-DE') AS MonatName, DATEPART(ISO_WEEK, Datum) AS KW_ISO, DAY(Datum) AS Tag, DATEPART(WEEKDAY, Datum) AS Wochentag, FORMAT(Datum,'dddd','de-DE') AS WochentagName, CASE WHEN DATEPART(WEEKDAY, Datum) IN (1,7) THEN 1 ELSE 0 END AS IstWochenende, 0 AS IstFeiertag, -- nachträglich befüllen NULL AS Feiertagsname, -- Fiskaljahr: Oktober–September (Beispiel) CASE WHEN MONTH(Datum) >= 10 THEN YEAR(Datum) + 1 ELSE YEAR(Datum) END AS FiskalJahr, CASE WHEN MONTH(Datum) IN (10,11,12) THEN 1 WHEN MONTH(Datum) IN (1,2,3) THEN 2 WHEN MONTH(Datum) IN (4,5,6) THEN 3 ELSE 4 END AS FiskalQuartal, CASE WHEN DATEPART(WEEKDAY, Datum) IN (1,7) THEN 0 ELSE 1 END AS IstArbeitstag, DATEPART(DAYOFYEAR, Datum) AS Jahrestag, DATEFROMPARTS(YEAR(Datum), MONTH(Datum), 1) AS MonatsBeginn, EOMONTH(Datum) AS MonatsEnde FROM Kalender OPTION (MAXRECURSION 4000); |
Ein Data Lake enthält täglich 50 GB neue Parquet-Dateien, alle im selben Ordner ohne Partitionierung. Eine Abfrage für den Monat März 2025 scannt alle 3 TB — und dauert 40 Minuten statt 90 Sekunden.
LÖSUNG:
✓ Zeitbasierte Partitionierung ist das Minimum: Jahr/Monat/Tag als Ordnerstruktur.
✓ Zusätzliche Partitionierung nach häufigen Filterdimensionen: Region, Quellsystem.
✓ Delta Lake: Z-Ordering als zusätzliche Optimierung für mehrdimensionale Filterabfragen.
|
bronze/ erp/ auftraege/ jahr=2025/ monat=03/ tag=01/ auftraege_20250301_001.parquet tag=02/ auftraege_20250302_001.parquet silver/ auftraege_bereinigt/ jahr=2025/ monat=03/ _delta_log/ ← Delta Lake Transaktionslog part-00000.parquet |
Alle Daten landen im selben Ordner — Rohdaten, bereinigte Daten und aggregierte Daten. Ein Downstream-Prozess greift versehentlich auf die Rohdaten statt auf die bereinigten Daten zu. Ergebnisse sind falsch, niemand bemerkt es sofort.
LÖSUNG:
✓ Medaillon-Architektur als zwingende Struktur: Bronze (roh) → Silver (bereinigt) → Gold (kuratiert).
✓ Strikte Schreibrechte: nur dedizierte Pipelines dürfen in Bronze schreiben. Silver-Prozesse lesen Bronze, schreiben Silver. Konsumenten lesen nur Gold.
✓ Metadaten-Tabelle dokumentiert welche Pipeline welche Schicht befüllt (Kapitel 4, Punkt 1).
Zwei Data Marts — einer für Controlling, einer für Vertrieb — definieren "Kunde" unterschiedlich. Im Controlling-Mart ist "Kunden-Umsatz" der Nettoumsatz nach Rabatten. Im Vertriebs-Mart ist er der Listenpreis. Berichte können nicht kombiniert werden.
LÖSUNG:
✓ Konformierte Dimensionen: eine zentrale Dim_Kunden, eine zentrale Dim_Datum, eine zentrale Dim_Artikel — alle Marts teilen dieselben Dimensionstabellen.
✓ KPI-Definitionen schriftlich festlegen bevor Modellierung beginnt: ein Glossar, keine Interpretationsspielräume.
✓ Data Dictionary als lebendes Dokument — generiert aus dbt-Dokumentation (Kapitel 7).
Ein DWH-Ladevorgang lädt täglich alle 200 Millionen Zeilen der Fact-Tabelle neu. Ladezeit: 6 Stunden. Das DWH ist 6 Stunden am Tag nicht aktuell. Das kostet bei Cloud-DWH außerdem ein Vielfaches der inkrementellen Alternative.
LÖSUNG:
✓ Wasserzeichen-basiertes inkrementelles Laden für alle Fact-Tabellen.
✓ Late Arriving Facts: Mechanismus für Buchungen, die rückwirkend eintreffen.
✓ Full Reload nur noch für Dimensionstabellen mit SCD-Typ-2-Prüfung — nicht für Facts.
|
-- Inkrementelles Laden mit Late-Arriving-Fact-Behandlung CREATE OR ALTER PROCEDURE dwh.SP_Lade_Fact_Auftraege_Inkrementell AS BEGIN SET NOCOUNT ON; DECLARE @LastLoad DATETIME2;
SELECT @LastLoad = MAX(_load_date) FROM dm.Fact_Auftraege; SET @LastLoad = ISNULL(@LastLoad, '2000-01-01');
-- Neue und geänderte Records seit letztem Load MERGE dm.Fact_Auftraege AS ziel USING ( SELECT -- Dimensionskeys per Lookup ermitteln ISNULL(dd.DatumKey, -1) AS DatumKey, ISNULL(dk.KundenKey, -1) AS KundenKey, ISNULL(da.ArtikelKey, -1) AS ArtikelKey, s.AuftragsNr, s.Nettobetrag, s.Menge, s.GeaendertAm FROM stg.Auftraege s LEFT JOIN dm.Dim_Datum dd ON dd.Datum = CAST(s.Auftragsdatum AS DATE) -- SCD Typ 2: Historischen Key zum Zeitpunkt der Buchung ermitteln LEFT JOIN dm.Dim_Kunden dk ON dk.KundenNr = s.KundenNr AND CAST(s.Auftragsdatum AS DATE) BETWEEN dk._valid_from AND dk._valid_to LEFT JOIN dm.Dim_Artikel da ON da.ArtikelNr = s.ArtikelNr AND da._is_current = 1 WHERE s.GeaendertAm > @LastLoad -- nur neue/geänderte OR s.Auftragsdatum > DATEADD(DAY,-7,GETDATE()) -- Late Arriving: 7 Tage ) AS quelle ON ziel.AuftragsNr = quelle.AuftragsNr WHEN MATCHED AND ziel.Nettobetrag <> quelle.Nettobetrag THEN UPDATE SET ziel.Nettobetrag = quelle.Nettobetrag, ziel._load_date = SYSUTCDATETIME() WHEN NOT MATCHED THEN INSERT (DatumKey, KundenKey, ArtikelKey, AuftragsNr, Nettobetrag, Menge) VALUES (quelle.DatumKey, quelle.KundenKey, quelle.ArtikelKey, quelle.AuftragsNr, quelle.Nettobetrag, quelle.Menge); END |
Power BI scannt täglich die gesamte 50-Millionen-Zeilen-Fact-Tabelle für jedes Dashboard-Refresh. Berichte sind langsam, die Datenbank wird belastet, DirectQuery ist nicht möglich.
LÖSUNG:
✓ Aggregations-Layer als vorberechnete Zusammenfassungen: monatlich, wöchentlich, nach Region und Produktgruppe.
✓ Power BI Import Mode auf Aggregationstabellen — DirectQuery nur für Detail-Drilldowns.
✓ SQL Server Indexed Views für die häufigsten Aggregationsmuster (kostenlos, automatisch genutzt).
|
-- Vorberechnete Aggregation: monatliche KPIs je Region und Warengruppe CREATE TABLE dm.Agg_Umsatz_Monatlich ( AggKey INT IDENTITY PRIMARY KEY, Jahr INT, Monat INT, FiskalQuartal INT, Region NVARCHAR(50), Warengruppe NVARCHAR(50), -- Additive Metriken — summierbar über alle Dimensionen Umsatz_Netto DECIMAL(18,2), Deckungsbeitrag DECIMAL(18,2), Auftragsanzahl INT, Kundenanzahl INT, -- Vorberechnete Verhältniszahlen — nicht additiv, nur auf dieser Ebene DB_Marge_Pct DECIMAL(8,4), Umsatz_Vorjahr DECIMAL(18,2), Wachstum_YoY_Pct DECIMAL(8,4), _aktualisiert DATETIME2 DEFAULT SYSUTCDATETIME() );
-- Job: täglich nach ETL-Abschluss aktualisieren (läuft in Sekunden) CREATE OR ALTER PROCEDURE dwh.SP_Aktualisiere_Agg_Umsatz AS BEGIN TRUNCATE TABLE dm.Agg_Umsatz_Monatlich; INSERT INTO dm.Agg_Umsatz_Monatlich (Jahr, Monat, FiskalQuartal, Region, Warengruppe, Umsatz_Netto, Deckungsbeitrag, Auftragsanzahl, Kundenanzahl, DB_Marge_Pct) SELECT dd.Jahr, dd.Monat, dd.FiskalQuartal, dk.Region, da.Warengruppe, SUM(f.Nettobetrag), SUM(f.Deckungsbeitrag), COUNT(DISTINCT f.AuftragsNr), COUNT(DISTINCT f.KundenKey), ROUND(SUM(f.Deckungsbeitrag) / NULLIF(SUM(f.Nettobetrag),0), 4) FROM dm.Fact_Auftraege f JOIN dm.Dim_Datum dd ON f.DatumKey = dd.DatumKey JOIN dm.Dim_Kunden dk ON f.KundenKey = dk.KundenKey JOIN dm.Dim_Artikel da ON f.ArtikelKey = da.ArtikelKey GROUP BY dd.Jahr, dd.Monat, dd.FiskalQuartal, dk.Region, da.Warengruppe; END |
Das Unternehmen kauft Azure Synapse, weil der Microsoft-Vertreter es empfohlen hat. Sechs Monate später ist weder das Schema noch die Schichtenarchitektur definiert. Jeder Data Engineer hat seinen eigenen Ordner, sein eigenes Format und seine eigene Namenskonvention. Das Ergebnis ist ein strukturierter Data Swamp.
LÖSUNG:
✓ Architecture Decision Record (ADR) vor der ersten Zeile Code: Welches Modell? Welche Schichten? Welche Konventionen?
✓ Proof of Concept auf einem kleinen, realen Datensatz — nicht auf Beispieldaten.
✓ Toolwahl folgt Architektur, nicht umgekehrt.
05
|
-- Vollständiges Star Schema für KMU-Umsatzreporting -- Dimensions-Tabellen CREATE TABLE dm.Dim_Datum (DatumKey INT PRIMARY KEY, /* → Kapitel 4, Punkt 4 */ Datum DATE); CREATE TABLE dm.Dim_Artikel (ArtikelKey INT IDENTITY PRIMARY KEY, ArtikelNr NVARCHAR(20), Bezeichnung NVARCHAR(200), Warengruppe NVARCHAR(50), Hauptgruppe NVARCHAR(50), EKPreis DECIMAL(18,4), _is_current BIT DEFAULT 1, _valid_from DATE, _valid_to DATE DEFAULT '9999-12-31'); CREATE TABLE dm.Dim_Mitarbeiter (MitarbeiterKey INT IDENTITY PRIMARY KEY, MitarbeiterNr INT, Vorname NVARCHAR(100), Nachname NVARCHAR(100), Abteilung NVARCHAR(50), Region NVARCHAR(50), Rolle NVARCHAR(50), _is_current BIT DEFAULT 1, _valid_from DATE, _valid_to DATE DEFAULT '9999-12-31');
-- Konformierte Dimensionen: von beiden Fact-Tabellen genutzt -- Fact-Tabelle 1: Aufträge (transaktional, tagesfein) -- Fact-Tabelle 2: Lagerbestand (periodisch, Stichtag je Monat)
-- Beziehungsdiagramm im Star Schema: -- -- Dim_Datum ──────────────┐ -- Dim_Kunden (SCD2) ──────┤ -- Dim_Artikel (SCD2) ─────┤──→ Fact_Auftraege -- Dim_Mitarbeiter ─────────┤ -- Dim_Auftrags_Flags ──────┘ -- -- Dim_Datum ──────────────┐ -- Dim_Artikel ────────────┤──→ Fact_Lagerbestand (Periodic Snapshot) -- Dim_Lager ──────────────┘
-- Periodic Snapshot Fact für Lagerbestand CREATE TABLE dm.Fact_Lagerbestand_Monat ( SnapshotKey INT IDENTITY PRIMARY KEY, DatumKey INT NOT NULL, -- Stichtag: letzter Tag des Monats ArtikelKey INT NOT NULL, LagerortKey INT NOT NULL, -- Bestandsmetriken (semi-additiv: summierbar über Artikel, nicht über Zeit!) Bestand_Menge DECIMAL(18,4), Bestand_Wert DECIMAL(18,2), Reichweite_Tage INT, -- nicht additiv UnterMeldebestand BIT, _load_date DATETIME2 DEFAULT SYSUTCDATETIME() ); |
|
-- Reporting-Views: stabile Schnittstelle für Power BI -- Schemaänderungen im DWH-Kern bleiben für Power BI unsichtbar CREATE OR ALTER VIEW rpt.V_Umsatz_Detail AS SELECT dd.Datum, dd.Jahr, dd.Quartal, dd.Monat, dd.MonatName, dd.KW_ISO, dd.FiskalJahr, dd.FiskalQuartal, dk.Name AS Kunde, dk.Region AS Kundenregion, dk.Umsatzklasse, da.Bezeichnung AS Artikel, da.Warengruppe, da.Hauptgruppe, dm2.Vorname + ' ' + dm2.Nachname AS Vertreter, dm2.Region AS Vertreterregion, f.AuftragsNr, f.Nettobetrag, f.Menge, f.Deckungsbeitrag, -- Berechnete Kennzahl: DB-Marge in % (nicht in Aggregationen summieren!) ROUND(f.Deckungsbeitrag / NULLIF(f.Nettobetrag,0) * 100, 2) AS DB_Marge_Pct FROM dm.Fact_Auftraege f JOIN dm.Dim_Datum dd ON f.DatumKey = dd.DatumKey JOIN dm.Dim_Kunden dk ON f.KundenKey = dk.KundenKey JOIN dm.Dim_Artikel da ON f.ArtikelKey = da.ArtikelKey JOIN dm.Dim_Mitarbeiter dm2 ON f.VertreterKey = dm2.MitarbeiterKey; |
06
|
-- Medaillon-Architektur in SQL Server (ohne Cloud-Lake) -- Bronze: Rohdaten — unveränderlich, append-only, volle Quelltreue CREATE SCHEMA bronze; CREATE TABLE bronze.Auftraege_Raw ( _row_id INT IDENTITY PRIMARY KEY, _src_system NVARCHAR(20) DEFAULT 'ERP', _loaded_at DATETIME2 DEFAULT SYSUTCDATETIME(), _src_filename NVARCHAR(200), -- bei CSV/Datei-Importen -- Alle Felder als NVARCHAR: keine Transformation in Bronze AuftragsNr NVARCHAR(100), KundenNr NVARCHAR(100), Auftragsdatum NVARCHAR(100), -- Rohformat, kein CAST Nettobetrag NVARCHAR(100), Status NVARCHAR(100), Rohdaten_JSON NVARCHAR(MAX) -- vollständiger Quelldatensatz );
-- Silver: Bereinigt — Typen korrekt, Nulls behandelt, Duplikate entfernt CREATE SCHEMA silver; CREATE OR ALTER VIEW silver.Auftraege AS SELECT _row_id, _src_system, _loaded_at, TRY_CAST(AuftragsNr AS INT) AS auftrags_nr, TRY_CAST(KundenNr AS INT) AS kunden_nr, TRY_CAST(Auftragsdatum AS DATE) AS auftragsdatum, TRY_CAST(Nettobetrag AS DECIMAL(18,2)) AS nettobetrag, UPPER(TRIM(Status)) AS status, -- Zeilen mit ungültigem Datum oder Betrag herausfiltern CASE WHEN TRY_CAST(Auftragsdatum AS DATE) IS NULL THEN 'UNGUELTIG_DATUM' WHEN TRY_CAST(Nettobetrag AS DECIMAL(18,2)) IS NULL THEN 'UNGUELTIG_BETRAG' WHEN UPPER(TRIM(Status)) IN ('STORNO','ENTWURF') THEN 'AUSGESCHLOSSEN' ELSE 'OK' END AS _dq_status FROM bronze.Auftraege_Raw WHERE TRY_CAST(Auftragsdatum AS DATE) IS NOT NULL;
-- Gold: Kuratiert — aggregiert, angereichert, business-ready CREATE SCHEMA gold; CREATE OR ALTER VIEW gold.Umsatz_Monatlich AS SELECT YEAR(auftragsdatum) AS jahr, MONTH(auftragsdatum) AS monat, SUM(nettobetrag) AS umsatz_netto, COUNT(DISTINCT auftrags_nr) AS auftragsanzahl, COUNT(DISTINCT kunden_nr) AS kundenanzahl FROM silver.Auftraege WHERE _dq_status = 'OK' GROUP BY YEAR(auftragsdatum), MONTH(auftragsdatum); |
In Microsoft Fabric ist das Delta-Format der Standard. Jede Tabelle im Lakehouse ist eine Delta-Tabelle — ACID-transaktional, versioniert, mit Time Travel.
|
-- Delta Lake Time Travel: historische Daten abrufen (Fabric / Databricks SQL) -- Zustand der Tabelle vor 7 Tagen SELECT * FROM silver.auftraege TIMESTAMP AS OF DATEADD(DAY, -7, CURRENT_TIMESTAMP);
-- Zustand zu einer bestimmten Version SELECT * FROM silver.auftraege VERSION AS OF 42;
-- Transaktionshistorie anzeigen DESCRIBE HISTORY silver.auftraege;
-- Delta Optimize: kleine Dateien zusammenführen (wichtig für Performance) OPTIMIZE silver.auftraege ZORDER BY (kunden_nr, auftragsdatum);
-- Vacuum: alte Versionen nach Aufbewahrungsfrist löschen (Default: 7 Tage) VACUUM silver.auftraege RETAIN 168 HOURS; -- 7 Tage |
07
dbt ist das Transformationswerkzeug, das sowohl für klassische DWH-Pipelines (SQL Server) als auch für Lakehouse-Architekturen (Fabric, Synapse) verwendet werden kann. Es bringt Versionskontrolle, Tests und automatische Dokumentation in die Transformationsschicht.
|
-- dbt-Modell: models/silver/stg_auftraege.sql -- Normalisierung und Qualitätsfilterung (Silver-Schicht) {{ config(materialized='incremental', unique_key='auftrags_nr', incremental_strategy='merge') }}
SELECT TRY_CAST(AuftragsNr AS INT) AS auftrags_nr, TRY_CAST(KundenNr AS INT) AS kunden_nr, TRY_CAST(Auftragsdatum AS DATE) AS auftragsdatum, TRY_CAST(Nettobetrag AS DECIMAL(18,2)) AS nettobetrag, UPPER(TRIM(Status)) AS status, _loaded_at, SYSUTCDATETIME() AS _transformiert_am FROM {{ source('bronze', 'Auftraege_Raw') }} WHERE TRY_CAST(Auftragsdatum AS DATE) IS NOT NULL AND TRY_CAST(Nettobetrag AS DECIMAL(18,2)) IS NOT NULL AND UPPER(TRIM(Status)) NOT IN ('STORNO','ENTWURF')
{% if is_incremental() %} AND _loaded_at > (SELECT MAX(_loaded_at) FROM {{ this }}) {% endif %} |
|
-- schema.yml — Qualitätsprüfungen als Konfiguration, nicht als Code -- version: 2 -- models: -- - name: stg_auftraege -- description: "Bereinigte Auftragsdaten aus dem ERP-System" -- columns: -- - name: auftrags_nr -- description: "Eindeutige Auftragsnummer" -- tests: -- - unique -- - not_null -- - name: kunden_nr -- tests: -- - not_null -- - relationships: -- to: ref('dim_kunden') -- field: kunden_nr_src -- - name: nettobetrag -- tests: -- - not_null -- - dbt_utils.accepted_range: -- min_value: 0 -- max_value: 10000000
-- Eigener Test: Umsatz-Reconciliation DWH vs. ERP -- tests/assert_umsatz_plausibel.sql SELECT COUNT(*) AS fehler FROM ( SELECT YEAR(auftragsdatum) AS jahr, MONTH(auftragsdatum) AS monat, SUM(nettobetrag) AS dwh_umsatz FROM {{ ref('stg_auftraege') }} GROUP BY YEAR(auftragsdatum), MONTH(auftragsdatum) ) dwh JOIN ( SELECT YEAR(Auftragsdatum) AS jahr, MONTH(Auftragsdatum) AS monat, SUM(Nettobetrag) AS erp_umsatz FROM {{ source('erp_raw', 'Auftraege') }} WHERE Status NOT IN ('STORNO','ENTWURF') GROUP BY YEAR(Auftragsdatum), MONTH(Auftragsdatum) ) erp USING (jahr, monat) WHERE ABS(dwh_umsatz - erp_umsatz) / NULLIF(erp_umsatz, 0) > 0.001 |
|
-- Jedes Modell bekommt eine Beschreibung — automatisch als Website generierbar -- models/marts/mart_umsatz.yml (Auszug) -- models: -- - name: mart_umsatz_monatlich -- description: > -- Monatliche Umsatzkennzahlen je Region und Warengruppe. -- Primäre Datenquelle für Power BI Umsatz-Dashboard. -- Wird täglich um 07:00 Uhr aktualisiert. -- meta: -- owner: "controlling@unternehmen.de" -- sla: "täglich bis 07:30 Uhr" -- power_bi_dataset: "Umsatz-Dashboard" -- columns: -- - name: umsatz_netto -- description: "Nettoumsatz nach Abzug aller Rabatte, ohne MwSt." -- meta: -- kpi_definition: "Gemäß Controlling-Handbuch §4.2, Stand 2025-01" -- - name: db_marge_pct -- description: "Deckungsbeitrag I in Prozent des Nettoumsatzes" -- meta: -- nicht_additiv: true -- power_bi_hinweis: "Nicht summieren — als gewichteter Durchschnitt berechnen" |
08
Microsoft Fabric (GA seit 2024) löst die DWH-vs-Data-Lake-Entscheidung für viele KMU auf, indem es beide Paradigmen auf einer Plattform vereint:
→ Lakehouse: Delta-Tabellen auf OneLake — offenes Format, Spark-kompatibel, mit ACID-Semantik.
→ Data Warehouse: Vollständiges T-SQL Data Warehouse auf denselben Daten — Star Schema, Views, Stored Procedures.
→ DirectLake Mode: Power BI liest Delta-Dateien direkt — keine Datenkopie in Power BI Dataset, keine Importverzögerung.
→ Data Factory: Pipelines für Extraktion aus ERP, CRM und APIs — ohne externen Dienst.
→ dbt on Fabric: dbt transformiert direkt in Fabric Lakehouse oder Warehouse — bekanntes Tooling, moderne Plattform.
|
-- Fabric Warehouse: volles T-SQL auf Lakehouse-Daten -- Dieselbe Abfrage läuft auf Delta-Dateien im Lakehouse SELECT YEAR(auftragsdatum) AS Jahr, dk.Region, SUM(f.nettobetrag) AS Umsatz, COUNT(DISTINCT f.kunden_nr) AS Kunden FROM lakehouse.silver_auftraege f JOIN lakehouse.dim_kunden dk ON f.kunden_nr = dk.kunden_nr AND dk._is_current = 1 WHERE auftragsdatum >= '2025-01-01' GROUP BY YEAR(auftragsdatum), dk.Region ORDER BY Umsatz DESC; -- Fabric optimiert automatisch ob Spark oder SQL Engine günstiger ist |
|
Szenario |
Empfehlung |
Begründung |
|
KMU, SQL Server On-Prem, < 100 GB |
DWH auf SQL Server + dbt |
Kein Cloud-Budget, bewährt, volle Kontrolle |
|
KMU, M365/Power BI Premium vorhanden |
Microsoft Fabric |
Lizenz inklusive, kein Extra-Budget, unified platform |
|
KMU, Azure bereits genutzt |
Azure Synapse oder Fabric |
Synapse für mehr Kontrolle, Fabric für weniger Komplexität |
|
KMU, Databricks-Affinität |
Databricks Lakehouse + dbt |
Wenn Python/Spark im Team vorhanden |
|
KMU, Greenfield ohne Cloud |
SQL Server + Medaillon-Schema |
Einfachster Einstieg ohne neue Technologie |
Die pragmatischste Architektur für ein KMU ohne spezialisiertes Data-Engineering-Team, 2026:
→ Extraktion: SQL Server Linked Server oder Azure Data Factory — täglich, inkrementell.
→ Bronze/Raw: Delta-Tabellen in Fabric Lakehouse oder Parquet auf ADLS2 — unveränderlich, vollständig.
→ Silver/Staging: dbt auf Fabric oder SQL Server — Normalisierung, Qualitätsprüfung, Typing.
→ Gold/DWH: Star Schema in Fabric Warehouse oder SQL Server dm-Schema — optimiert für Power BI.
→ Reporting: Power BI mit DirectLake (Fabric) oder DirectQuery (SQL Server) — immer aktuelle Daten.
→ Orchestrierung: SQL Agent (On-Prem) oder Fabric Data Factory Pipelines — täglicher Lauf, Alerting bei Fehler.
09
|
-- Einfacher Datenkatalog ohne Azure Purview CREATE TABLE catalog.Objekte ( ObjektID INT IDENTITY PRIMARY KEY, Schema_Name NVARCHAR(50), Objekt_Name NVARCHAR(200), Objekt_Typ NVARCHAR(20), -- TABELLE / VIEW / FUNKTION / PIPELINE Schicht NVARCHAR(10), -- BRONZE / SILVER / GOLD / RPT Beschreibung NVARCHAR(MAX), Owner_Email NVARCHAR(200), SLA NVARCHAR(100), -- 'täglich bis 07:30 Uhr' Quellsysteme NVARCHAR(500), -- 'ERP, CRM' Downstream NVARCHAR(500), -- 'Power BI Umsatz-Dashboard' Aktualisierung NVARCHAR(50), -- 'Täglich 06:00 Uhr' Letzte_Pruefung DATE, Qualitaet NVARCHAR(10) DEFAULT 'UNGEPRUEFT', Erstellt DATETIME2 DEFAULT SYSUTCDATETIME(), GeaendertAm DATETIME2 DEFAULT SYSUTCDATETIME() );
-- DWH-Freshness-Monitoring: wann wurde welches Objekt zuletzt geladen? CREATE OR ALTER VIEW catalog.V_Freshness_Status AS SELECT c.Schema_Name + '.' + c.Objekt_Name AS Objekt, c.Schicht, c.SLA, c.Owner_Email, -- Letztes Ladedatum aus _load_date Spalte (SELECT MAX(_load_date) FROM dm.Fact_Auftraege) AS Letzte_Ladung, DATEDIFF(HOUR, (SELECT MAX(_load_date) FROM dm.Fact_Auftraege), GETDATE()) AS Stunden_Zurueck, CASE WHEN DATEDIFF(HOUR, (SELECT MAX(_load_date) FROM dm.Fact_Auftraege), GETDATE()) < 25 THEN 'GRUEN' WHEN DATEDIFF(HOUR, (SELECT MAX(_load_date) FROM dm.Fact_Auftraege), GETDATE()) < 49 THEN 'GELB' ELSE 'ROT' END AS Freshness_Ampel FROM catalog.Objekte c WHERE c.Objekt_Name = 'Fact_Auftraege'; |
|
-- Kostenmonitor: Azure-Kosten täglich protokollieren (via Azure Cost Management API) CREATE TABLE monitor.Azure_Kosten ( KostenID INT IDENTITY PRIMARY KEY, Datum DATE, Dienst NVARCHAR(100), -- 'Azure Synapse', 'ADLS2', 'Fabric' Ressource NVARCHAR(200), Kosten_EUR DECIMAL(10,4), Einheit NVARCHAR(50), -- 'DWU-Stunden', 'TB', 'vCore-Stunden' Budget_EUR DECIMAL(10,2), -- monatliches Budget für diesen Dienst Budget_Verbrauch_Pct AS ROUND(Kosten_EUR / NULLIF(Budget_EUR / 30.0, 0) * 100, 1) PERSISTED );
-- Alert wenn Tageskosten > 110% des Budget-Tagesdurchschnitts -- Wird täglich als SQL Agent Job ausgeführt SELECT Dienst, SUM(Kosten_EUR) AS Heute_EUR, MAX(Budget_EUR)/30 AS Budget_Tag_EUR, CASE WHEN SUM(Kosten_EUR) > MAX(Budget_EUR)/30 * 1.1 THEN 'BUDGET-ALERT: ' + Dienst + ' überschreitet Tagesbudget!' ELSE 'OK' END AS Status FROM monitor.Azure_Kosten WHERE Datum = CAST(GETDATE() AS DATE) GROUP BY Dienst HAVING SUM(Kosten_EUR) > MAX(Budget_EUR)/30 * 1.1; |
Die vier wichtigsten Kostenhebel in Cloud-Architekturen:
→ Pause/Resume für DWH-Compute: Azure Synapse und Fabric Warehouse können außerhalb der Nutzungszeiten pausiert werden — spart 60–80 % der Compute-Kosten bei nachtaktiven Workloads.
→ Partitionierung und Pruning: Gut partitionierte Tabellen scannen nur relevante Partitionen — reduziert Compute-Kosten proportional zur Partitionsgröße.
→ Result Set Caching: Wiederkehrende Power-BI-Abfragen treffen den Cache statt die Compute-Engine — bei stabilen Dashboards bis zu 90 % Kostenreduktion.
→ Materialized Views für häufige Aggregationen: Vorberechnete Ergebnisse werden gespeichert und automatisch aktuell gehalten — kein teurer Full-Scan bei jeder Abfrage.
10
|
|
VOR DEM START Wählen Sie einen einzigen Fachbereich als Piloten — Controlling/Umsatz ist fast immer der beste Einstieg. Erstellen Sie ein vollständiges Backup aller betroffenen Quellsysteme. Benennen Sie einen technischen Verantwortlichen (Data Engineer) und einen fachlichen Sponsor (Controller oder CFO). Führen Sie den Entscheidungsmatrix-Check aus Kapitel 3 durch — die Architekturwahl steht vor dem ersten Code. |
■ TAG 1-2: IST-ZUSTAND DOKUMENTIEREN
■ Alle bestehenden Datenquellen inventarisieren: welche Systeme, welche Tabellen, welche Datenmengen
■ Alle Power-BI-Berichte auflisten: welche Datenquelle, welche Abfragen, Aktualisierungsfrequenz
■ Direkt-auf-ERP-Verbindungen in Power BI identifizieren — das ist Ihre Brandschutzliste
■ Datenvolumen messen: wie viele Zeilen hat die größte Quelltabelle, wie viel wächst sie pro Tag?
■ TAG 3-4: ARCHITEKTURENTSCHEIDUNG TREFFEN
■ Entscheidungsmatrix aus Kapitel 3 mit dem technischen Team ausfüllen
■ Plattformentscheidung treffen: SQL Server On-Prem, Fabric oder Azure Synapse?
■ Architecture Decision Record (ADR) schreiben: Entscheidung, Begründung, Alternativen
■ Modellierungsentscheidung: Star Schema oder Medaillon? Für Einstieg: Star Schema auf SQL Server
■ TAG 5-7: FUNDAMENT LEGEN
■ DWH-Datenbank anlegen: Schemas stg, core/dm, rpt (DWH) oder bronze/silver/gold (Lakehouse)
■ Naming Conventions festlegen: Präfixe, Groß-/Kleinschreibung, Sprache der Bezeichner
■ Datumsdimension generieren (Kapitel 4, Punkt 4) — einmalig, dauerhaft
■ ETL-Protokolltabelle anlegen: alle späteren Ladeprozesse protokollieren von Anfang an
■ TAG 8-10: STAGING-PIPELINE FÜR UMSATZDATEN
■ Staging-Extraktion aus ERP-Auftragstabelle implementieren — inkrementell von Anfang an
■ Row-Hash für Änderungserkennung auf alle Staging-Records berechnen
■ Erste Qualitätsprüfungen: NULL-Check Pflichtfelder, Datumsbereich plausibel, Beträge positiv
■ Protokoll: Zeilen geladen, Zeilen fehlerhaft, Laufzeit — täglich als SQL Agent Job
■ TAG 11-13: ERSTE DIMENSION UND FACT-TABELLE
■ Dim_Kunden mit SCD Typ 2 implementieren (Kapitel 4, Punkt 2)
■ Dim_Artikel als SCD Typ 1 (wenn Historisierung nicht benötigt) oder Typ 2
■ Fact_Auftraege mit Surrogate-Key-Lookup auf alle Dimensionen
■ Datenqualitäts-Check: Fact ohne passenden Dimensionseintrag → Quarantäne, kein Verwerfen
■ TAG 14: ERSTER POWER-BI-ANSCHLUSS
■ Reporting-View rpt.V_Umsatz_Detail anlegen (Kapitel 5.2)
■ Bestehenden Power-BI-Bericht auf DWH-View umstellen — ERP-Direktverbindung entfernen
■ Zahlenvergleich: DWH-Zahlen vs. ERP-Zahlen — Abweichungen dokumentieren und klären
■ Laufzeit messen: Power-BI-Refresh auf DWH-View vs. vorher auf ERP-Tabelle
■ TAG 15-17: MODELL VERVOLLSTÄNDIGEN
■ Dim_Datum vollständig generieren: Fiskaljahr, ISO-Woche, Feiertage ergänzen
■ Dim_Mitarbeiter/Vertreter implementieren
■ Aggregations-Tabelle für monatliche KPIs anlegen (Kapitel 4, Punkt 9)
■ dbt installieren und erste Modelle als dbt-SQL migieren — Qualitätstests aktivieren
■ TAG 18-20: GOVERNANCE EINRICHTEN
■ Datenkatalog-Tabelle anlegen und alle DWH-Objekte eintragen (Kapitel 9.1)
■ Freshness-Monitoring: täglich prüfen, ob alle Objekte SLA einhalten
■ Wöchentlicher Qualitätsbericht: Vollständigkeit, Freshness, offene DQ-Fehler per Mail
■ Berechtigungen: nur rpt-Schema für Power-BI-Service-Account, dm und stg intern
■ TAG 21: RECONCILIATION AUTOMATISIEREN
■ Tägliche Reconciliation DWH vs. ERP: Umsatz, Auftragsanzahl, Kundenanzahl
■ Alert bei Abweichung > 0,1 %: Database Mail an Data Engineer und Controller
■ Reconciliation-Ergebnis im Power-BI-Dashboard sichtbar machen (Ampel)
■ Erste dbt-Test-Suite ausführen und alle Fehler beheben
■ TAG 22-25: VOLLAUTOMATISCHER PRODUKTIONSBETRIEB
■ SQL Agent Job-Kette finalisieren: Staging → Dimensionen → Facts → Aggregationen → Qualitätsprüfung
■ Fehlerbehandlung: bei Job-Fehler → Rollback → Alert → kein falsches Datum in Power BI
■ Laufzeitoptimierung: welcher Job dauert am längsten? Indizes, Inkrementalität prüfen
■ Monitoring-Dashboard in Power BI: Job-Status, Laufzeiten, Freshness, Reconciliation
■ TAG 26-28: ZWEITEN FACHBEREICH VORBEREITEN
■ Nächsten Fachbereich identifizieren: Lager, Einkauf oder Personalcontrolling?
■ Konformierte Dimensionen prüfen: Dim_Datum und Dim_Artikel sind bereits vorhanden — wiederverwenden
■ Neuen Pilot-Controller einbinden: Anforderungen aufnehmen, KPI-Definitionen schriftlich festhalten
■ Architekturentscheidung für zweiten Bereich: Star Schema passt immer in dasselbe Modell
■ TAG 29-30: ABSCHLUSS UND DOKUMENTATION
■ Performance-Messung: Vorher-Nachher für Power-BI-Refresh-Zeiten und ERP-Last
■ ADR aktualisieren: Was haben wir anders gemacht als geplant? Was würden wir wieder so machen?
■ dbt-Dokumentation generieren: automatische Website mit allen Modellen, Tests und Lineage
■ Übergabedokumentation für neuen Entwickler: wie wird die Pipeline betrieben, wie debuggt?
■ Ergebnis feiern — ein strukturiertes Datenfundament ist das Fundament aller zukünftigen BI-Arbeit! ■
|
|
ERGEBNIS NACH 30 TAGEN Ihr Ergebnis nach 30 Tagen: Power BI greift nicht mehr direkt auf Produktivdatenbanken zu, eine vollständige Historisierung der Kundendimension ist vorhanden, tägliche Reconciliation sichert Datenqualität automatisch, ein Aggregations-Layer macht Power-BI-Refresh schnell und ein Datenkatalog dokumentiert das neue Fundament. Das ist der solide Ausgangspunkt für alle weiteren BI-Ausbauschritte. |
Die in diesem Dokument enthaltenen Informationen, Skripte und Architekturempfehlungen wurden nach bestem Wissen und Gewissen erarbeitet. Da jede Daten- und Systemlandschaft individuell ist, übernimmt der Autor keinerlei Haftung für Datenverlust, Systemausfälle, unerwartete Cloud-Kosten, fehlerhafte Datenkonsolidierungen oder sonstige unmittelbare oder mittelbare Schäden.
Architekturentscheidungen wie die Wahl zwischen Data Warehouse, Data Lake und Lakehouse haben langfristige Konsequenzen. Treffen Sie diese Entscheidungen auf Basis Ihrer eigenen Anforderungsanalyse — dieses Kit liefert Orientierung, ersetzt aber keine individuelle Architekturberatung.
Angaben zu Cloud-Diensten (Azure Synapse, Microsoft Fabric, Databricks) entsprechen dem Stand März 2026. Cloud-Preise, Servicefeatures und Lizenzmodelle ändern sich regelmäßig. Konfigurieren Sie Budgetalerts und Spending Caps, bevor Sie Cloud-Dienste produktiv einsetzen.
Genannte Performance-Verbesserungen, Kosteneinsparungen und Projektzeiträume sind Erfahrungswerte aus realen KMU-Umgebungen und stellen keine verbindliche Zusicherung dar.
Die Inhalte beziehen sich auf SQL Server 2022/2025, Microsoft Fabric (Stand März 2026), dbt Core 1.8+, Azure Synapse Analytics und Databricks Runtime 15+. Durch künftige Updates können Abweichungen entstehen.
© 2026 Sascha Hess, xenosystems.de. Alle Rechte vorbehalten. Dieses Dokument ist für den persönlichen oder betriebsinternen Gebrauch des Käufers lizenziert.
SQL Server, Azure Synapse, Microsoft Fabric, Power BI und Azure Data Lake Storage sind eingetragene Marken der Microsoft Corporation. dbt ist eine Marke von dbt Labs, Inc. Databricks und Delta Lake sind Marken der Databricks, Inc. Apache Iceberg ist ein Projekt der Apache Software Foundation.
Es gilt ausschließlich deutsches Recht. Gerichtsstand für alle Streitigkeiten ist, soweit gesetzlich zulässig, Weimar, Thüringen, Deutschland.
Sascha Hess ist Diplom-Biologe und IT-Professional mit über 20 Jahren Erfahrung in der Administration von ERP-, BI- und Datenbanksystemen. Er hat mehr als 300 Oracle- und SQL-Server-Instanzen administriert und betreut — von mittelständischen KMU bis zu Universitäten und Energieversorgern.
Sein Ansatz verbindet naturwissenschaftliche Präzision mit hochgradiger IT-Spezialisierung. Schwerpunkte: Data-Warehouse-Architektur, Lakehouse-Design, SQL Server Performance-Tuning, ERP-Einführungen, Business Intelligence (Power BI, DeltaMaster), dbt, Prozessdigitalisierung und IT-Interim-Management.
Web: www.xenosystems.de | E-Mail: info@xenosystems.de | Standort: Weimar, Thüringen / Remote
|
Service |
Beschreibung |
|
BI-Architektur-Review |
Analyse Ihrer bestehenden Datenarchitektur — DWH-Assessment, Architekturempfehlung (DWH vs. Lakehouse), Modernisierungsfahrplan. Scope: 3-5 Tage. |
|
Data Warehouse Aufbau |
Implementierung eines produktionsfertigen Star-Schema-DWH auf SQL Server oder Microsoft Fabric — mit Staging, SCD Typ 2, Aggregations-Layer und Power-BI-Anbindung. |
|
Lakehouse Migration |
Migration von bestehenden DWH- oder BI-Strukturen in eine Medaillon-Architektur auf Fabric oder Azure Synapse — inkl. dbt-Einführung und Wissenstransfer. |
|
BI-Dashboard-Aufbau |
Power BI / DeltaMaster Dashboards inkl. ETL-Strecken und strukturiertem Data-Warehouse-Fundament — keine Direktverbindungen auf Produktivdatenbanken. |
|
Interim IT-Management |
Übernahme der IT-Steuerung auf Zeit — Budgetplanung, Dienstleister-Management, strategische IT- und Datenarchitektur-Ausrichtung. |
Vollständiges Dokument
Strategische Wissens-Roadmap · Checklisten · Praxisbeispiele
49,90 €
Sichere Zahlung über PayPal · Sofort-Download nach Zahlungseingang