Wenn ETL zur Bremse wird
Viele ETL-Prozesse sind historisch gewachsen.
Und heute: langsam, schwer wartbar, fehleranfällig.
Meist läuft’s so:
Daten aus System A → Staging → Transformationen → Zielsystem B
Und dazwischen: unnötige Kopien, Casts, Cursor, Abfragen ohne Filter.
Wenn Du willst, dass der Datenfluss effizient bleibt, musst Du aufräumen.
Ich zeig Dir, wo Du ansetzen kannst.
Typische ETL-Sünden
Problem | Folge |
---|---|
Kein WHERE bei Datenzugriff | unnötiger Traffic |
Cursors statt Sets | viel CPU, wenig Nutzen |
Spaltenkonvertierungen | I/O + CPU + schlechte Indizes |
Fehlerhandling im SSIS | schwer nachvollziehbar |
Kein Logging der Schritte | Debuggen wird Ratespiel |
Datenmenge begrenzen – direkt an der Quelle
-- Schlechte Variante
SELECT * FROM ERP.Produkte;
-- Besser
SELECT id, bezeichnung, preis
FROM ERP.Produkte
WHERE aktiv = 1
AND geändert_am >= @letztes_Laufdatum;
Erst holen, was wirklich gebraucht wird.
Und lieber kleine Deltas als Vollabzüge.
Kein CAST im Ziel, sondern sauber typisieren
-- Falsch: Conversion bei Insert
INSERT INTO DWH.Ziel
SELECT
CAST(id AS INT),
CAST(preis AS DECIMAL(10,2))
FROM Staging.Quelle;
-- Besser: gleich in Staging korrekt definieren
Staging-Tabellen sollten das Format des Quellsystems exakt spiegeln.
Transformationen gehören danach.
Row-by-Row vermeiden
-- Cursor? Lass es.
DECLARE cur CURSOR FOR
SELECT kunde_id FROM dbo.Kunden;
-- Besser: set-based arbeiten
INSERT INTO DWH.Segmente
SELECT kunde_id, 'NEU'
FROM dbo.Kunden
WHERE erstellt_am >= @stichtag;
Set-basierte Operationen sind schneller, einfacher zu warten und paralleler nutzbar.
Robustheit durch Logging
INSERT INTO ETL.Log (prozess, startzeit, status)
VALUES ('Kundentransfer', GETDATE(), 'gestartet');
-- Schritte ausführen...
UPDATE ETL.Log
SET status = 'erfolgreich', endzeit = GETDATE()
WHERE prozess = 'Kundentransfer'
AND status = 'gestartet';
So weißt Du:
- wann lief was?
- wie lange?
- mit welchem Ergebnis?
Fehlerbehandlung direkt in SQL
BEGIN TRY
-- z. B. Upsert-Logik
MERGE INTO dbo.KundenZiel AS ziel
USING dbo.KundenNeu AS quelle
ON ziel.id = quelle.id
WHEN MATCHED THEN
UPDATE SET ziel.name = quelle.name
WHEN NOT MATCHED THEN
INSERT (id, name) VALUES (quelle.id, quelle.name);
END TRY
BEGIN CATCH
INSERT INTO ETL.Fehlerlog
VALUES (ERROR_MESSAGE(), GETDATE(), 'Kunden-MERGE');
END CATCH
Wenn was schiefgeht, weißt Du wenigstens wo.
Performance-Tipp: Minimal Logging aktivieren
-- Nur bei einfachen Inserts in leere Tabellen
ALTER TABLE dbo.StagingTab
SWITCH TO dbo.ZielTab;
-- Oder:
SELECT * INTO dbo.Temp FROM Quelle WITH (TABLOCK);
So nutzt Du minimal logging – spart I/O und Transaction Log.
Ausblick: Weg vom SSIS-Monolithen
Wenn Du noch alles im SSIS hast:
Splitte auf:
- SQL-Stored Procedures für Transformationen
- Powershell für Orchestrierung
- SQL Agent für Scheduling
- Logging in eigener ETL-Logtabelle
So bist Du flexibler, schneller, portabler.
Gerade bei hybriden Architekturen.
Mein Fazit
Gute ETL-Prozesse sind wie gute Lagerlogistik:
Klarer Fluss, wenig Umwege, keine Dopplungen.
No responses yet