Xenosystems Logo
Sascha Hess

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

 


Rechtliche Hinweise und Haftungsausschluss

 

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.

 


 

 

Inhaltsverzeichnis

 

 

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

Einleitung

 

Warum die falsche Architekturwahl Jahre kostet

 

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

Grundkonzepte

 

Data Warehouse, Data Lake und Lakehouse — Definitionen, Geschichte und Kernunterschiede

 

2.1 Das Data Warehouse — Schema on Write

 

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

 

 

2.2 Der Data Lake — Schema on Read

 

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.

 

2.3 Das Lakehouse — Schema on Write auf flexiblem Speicher

 

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

 

2.4 Die drei dominanten Plattformstrategien 2026

 

  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

Entscheidungsmatrix

 

12 Kriterien mit Bewertungsschema für jede Situation

 

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.

 

3.1 Sonderfall: Power BI als Einstiegspunkt

 

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

Die 10 Architektur-Fallen

 

Typische Fehler beim Aufbau von DWH und Data Lake — mit Sofort-Korrekturen

 

01 Der Data Lake als Dateifriedhof

 

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

);

 

 

02 Das DWH ohne Historisierung

 

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

 

 

 

 

 

 

03 Das Star Schema mit zu vielen Dimensionen

 

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()

);

 

 

04 Fehlende Datumsdimension

 

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);

 

 

05 Daten im Lake ohne Partitionierung

 

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

 

 

06 Keine Trennung von Raw und Curated im Lake

 

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).

 

07 DWH-Modell ohne Konformierte Dimensionen

 

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).

 

08 Fehlende Inkrementalität — täglich alles neu laden

 

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

 

 

09 Power BI direkt auf Fact-Tabellen — kein Aggregations-Layer

 

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

 

 

10 Kein Architekturkonzept — Tool-First-Entscheidungen

 

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

Data Warehouse in der Praxis

 

Star Schema, SCD, Fact-Tabellen und Aggregations-Layer

 

5.1 Das vollständige Star Schema — KMU-Standardmodell

 

-- 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()

);

 

 

 

 

 

5.2 Reporting-Layer als Power-BI-Schnittstelle

 

-- 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

Data Lake und Lakehouse

 

Medaillon-Architektur, Delta-Format und Partitionierungsstrategien

 

6.1 Die Medaillon-Architektur — drei Schichten, eine Logik

 

-- 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);

 

 

6.2 Delta Lake auf Microsoft Fabric

 

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 als gemeinsame Transformations-Schicht

 

Modelle, Tests und Dokumentation für DWH und Lakehouse

 

7.1 dbt-Projektstruktur für DWH und Lakehouse

 

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 %}

 

 

7.2 dbt Tests — Qualitätssicherung deklarativ

 

-- 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

 

 

7.3 dbt Dokumentation als lebendiges Data Dictionary

 

-- 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

Moderne Hybridarchitekturen

 

Fabric, Synapse und das Ende der Entweder-oder-Entscheidung

 

8.1 Microsoft Fabric — DWH und Lakehouse in einer Plattform

 

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

 

 

 

 

 

 

 

8.2 Wann welche Plattform — Entscheidungsleitfaden 2026

 

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

 

8.3 Die hybride Referenzarchitektur für den deutschen KMU-Mittelstand

 

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

Governance, Qualität und Kosten

 

Datenkatalog, Qualitätssicherung und Cloud-Kostensteuerung

 

9.1 Datenkatalog — Minimum Viable Version in SQL

 

-- 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';

 

 

 

 

 

 

9.2 Cloud-Kostensteuerung — die vier wichtigsten Hebel

 

-- 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

30-Tage-Architekturplan

 

Vom konzeptlosen Reporting zum strukturierten Datenfundament

 

 

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.

 

WOCHE 1: ANALYSE UND ARCHITEKTURENTSCHEIDUNG

 

■ 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

 

WOCHE 2: STAGING UND ERSTE DIMENSION

 

■ 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

 

WOCHE 3: WEITERE DIMENSIONEN UND QUALITÄTSSICHERUNG

 

■ 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

 

WOCHE 4: AUTOMATISIERUNG UND AUSBLICK

 

■ 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.

 


 

Ausführlicher Haftungsausschluss und Lizenzbestimmungen

 

1. Allgemeiner Haftungsausschluss

 

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.

 

2. Cloud-Kosten und Serviceverfügbarkeit

 

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.

 

3. Keine Ergebnisgarantie

 

Genannte Performance-Verbesserungen, Kosteneinsparungen und Projektzeiträume sind Erfahrungswerte aus realen KMU-Umgebungen und stellen keine verbindliche Zusicherung dar.

 

4. Versionsabhängigkeit

 

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.

 

5. Urheberrecht und Nutzungsrechte

 

© 2026 Sascha Hess, xenosystems.de. Alle Rechte vorbehalten. Dieses Dokument ist für den persönlichen oder betriebsinternen Gebrauch des Käufers lizenziert.

 

6. Markenrechte

 

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.

 

7. Anwendbares Recht und Gerichtsstand

 

Es gilt ausschließlich deutsches Recht. Gerichtsstand für alle Streitigkeiten ist, soweit gesetzlich zulässig, Weimar, Thüringen, Deutschland.

 


 

Über den Autor

 

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

BI und Governance 2026

Strategische Wissens-Roadmap · Checklisten · Praxisbeispiele

49,90 €

Sichere Zahlung über PayPal · Sofort-Download nach Zahlungseingang