Daten in Amazon Redshift validieren
Ein praxisnaher Leitfaden zur Datenqualität in Amazon Redshift — die sechs Prüfungen, die jede Tabelle braucht, wie Sie sie aus der WLM-Queue heraushalten, die Falle der nicht durchgesetzten Constraints und wie Sie alles als versionierten Data Contract betreiben.
· 8 min read
Um Daten in Amazon Redshift zu validieren, formulieren Sie jede Erwartung als Aggregatabfrage, die eine Anzahl von Verstößen zurückgibt, und führen den Stapel nach jedem Ladelauf aus. Die sechs Prüfungen, die sich lohnen, sind: Nullwerte in Pflichtspalten, doppelte Schlüssel, Werte außerhalb einer erlaubten Menge, Zahlen außerhalb eines plausiblen Bereichs, fehlerhaft formatierte Zeichenketten und veraltete Zeilen. Wegen seiner Postgres-Abstammung ist das meiste SQL vertraut — zwei Dinge aber nicht: Constraints werden in Redshift deklariert und nie durchgesetzt, sodass der Optimizer aus einem doppelten Schlüssel falsche Antworten ableiten kann, und Validierungsabfragen konkurrieren um Slots in einer WLM-Queue, die auch Ihr ETL nutzt.
Warum Redshift Sorgfalt verlangt
Constraints sind Hinweise, keine Regeln. Redshift akzeptiert Deklarationen von PRIMARY KEY, UNIQUE und FOREIGN KEY und setzt keine davon je durch. Schlimmer noch: Der Planner vertraut ihnen. Wenn Sie order_id als eindeutig deklarieren und sie es nicht ist, kann eine Abfrage, die sich auf diese Annahme stützt, falsche Ergebnisse liefern und nicht bloß langsame. Eindeutigkeit zu validieren ist in Redshift keine vorsorgliche Hygiene — es schützt die Korrektheit jeder nachgelagerten Abfrage.
Alles teilt sich eine Queue. Redshift führt Abfragen über Workload Management aus. Ein Validierungsdurchlauf voller Full Table Scans, der zeitgleich mit dem nächtlichen ETL eingereicht wird, reiht sich dahinter ein — oder nimmt ihm, schlimmer noch, Slots weg. Geben Sie der Validierung eine eigene WLM-Queue mit moderater Nebenläufigkeit und eine Query Monitoring Rule, die alles abbricht, was über einer Schwelle läuft.
Veraltete Statistiken verändern, was „billig" heißt. Nach einem großen COPY sind die Tabellenstatistiken veraltet, bis ANALYZE läuft. Pläne, die aus veralteten Statistiken gewählt werden, können aus einem schnellen Aggregat einen Broadcast Join machen. Validieren Sie nach ANALYZE, nicht davor.
Jenseits dieser drei Punkte hat Validierung in Redshift dieselbe Gestalt wie überall sonst — der vollständige Leitfaden zur Datenvalidierung legt sie von Anfang bis Ende dar.
Die sechs Prüfungen, die jede Tabelle braucht
1. Vollständigkeit — Nullwerte in Pflichtspalten
SELECT COUNT(*) AS violations
FROM sales.orders
WHERE order_id IS NULL;
Redshift ist spaltenorientiert, liest hier also nur die Spalte order_id — billig selbst bei einer breiten Faktentabelle. Schreiben Sie in einer Prüfung nie SELECT *; damit verschenken Sie genau diesen Vorteil.
2. Eindeutigkeit — doppelte Geschäftsschlüssel
SELECT COUNT(*) AS violations
FROM (
SELECT order_id
FROM sales.orders
WHERE order_id IS NOT NULL
GROUP BY order_id
HAVING COUNT(*) > 1
) dupes;
Das ist die Prüfung, die Sie auf jeder Redshift-Tabelle zuerst laufen lassen sollten. Duplikate entstehen regelmäßig: ein COPY, der nach einem Teilabbruch wiederholt wurde, ein als Delete-dann-Insert umgesetztes MERGE, bei dem der Delete-Filter danebenlag, ein Upstream-Extrakt, der für dasselbe Zeitfenster erneut lief. Da der deklarierte Primärschlüssel nichts tut, wird sie sonst nichts erwischen.
Hat die Tabelle einen Sort Key auf dem Geschäftsschlüssel, läuft das GROUP BY gegen sortierte Blöcke und ist deutlich günstiger. Es lohnt sich, Sort Keys mit diesem Gedanken auszuwählen.
3. Konformität — Werte außerhalb einer erlaubten Menge
SELECT COUNT(*) AS violations
FROM sales.orders
WHERE status IS NOT NULL
AND status NOT IN ('pending', 'paid', 'shipped', 'refunded');
Behalten Sie die Null-Absicherung — NULL NOT IN (...) ergibt NULL, die Zeile fällt heraus, und eine Spalte mit vielen Nullwerten meldet sich sauber.
Längen von VARCHAR zählen in Redshift Bytes, nicht Zeichen. Ein Vier-Byte-Emoji in einer VARCHAR(10)-Spalte wird beim Laden abgeschnitten, und ein abgeschnittener Wert scheitert an der Prüfung auf erlaubte Werte aus einem Grund, der nichts mit dem Quellsystem zu tun hat. Dimensionieren Sie Textspalten großzügig.
4. Genauigkeit — Zahlen außerhalb eines plausiblen Bereichs
SELECT COUNT(*) AS violations
FROM sales.orders
WHERE total_amount IS NOT NULL
AND (total_amount < 0 OR total_amount > 100000);
Nutzen Sie DECIMAL/NUMERIC für Geldbeträge. Die DECIMAL-Arithmetik von Redshift kann bei Aggregationen zudem still in eine größere Nachkommastellenzahl überlaufen — eine Bereichsprüfung auf der Rohspalte ist deshalb verlässlicher als eine auf einer berechneten Summe.
5. Konformität — fehlerhaft formatierte Identifier
Redshift behält die Regex-Operatoren von Postgres:
SELECT COUNT(*) AS violations
FROM sales.orders
WHERE reference IS NOT NULL
AND reference !~ '^ORD-[0-9]{6}#39;;
~ ist Groß-/Kleinschreibung-sensitiv, ~* nicht, !~ negiert. Auch SIMILAR TO sowie REGEXP_COUNT/REGEXP_SUBSTR stehen zur Verfügung. Es ist keine Musterübersetzung nötig — anders als bei SQL Server ist das Muster, das Sie schreiben, auch das Muster, das läuft.
6. Aktualität — Freshness
SELECT COUNT(*) AS violations
FROM sales.orders
WHERE created_at < GETDATE() - INTERVAL '24 hours';
GETDATE() liefert in Redshift UTC — das Gegenteil des Verhaltens in SQL Server und eine echte Quelle von Verwirrung, wenn man Regeln zwischen beiden portiert. Auch SYSDATE liefert UTC. Speichern Sie Zeitstempel als TIMESTAMP (Redshift speichert keine Zeitzone) und halten Sie per Konvention alles in UTC.
Für eine Prüfung auf abgeschlossene Ladeläufe, die keine Tabellendaten anfasst, trägt SVV_TABLE_INFO die Metadaten pro Tabelle günstig bei.
Referenzielle Integrität
SELECT COUNT(*) AS violations
FROM sales.orders o
LEFT JOIN sales.customers c ON o.customer_id = c.id
WHERE o.customer_id IS NOT NULL
AND c.id IS NULL;
Weil Fremdschlüssel nicht durchgesetzt werden, sind verwaiste Zeilen nach einem teilweisen Backfill häufig. Für die Kosten dieser Prüfung zählt der Distribution Style: Sind beide Tabellen per DISTKEY auf der Join-Spalte verteilt, ist der Join lokal auf jedem Slice; andernfalls verteilt Redshift eine Seite über den Cluster um. Bei großen Tabellen ist das der Unterschied zwischen Sekunden und Minuten.
Ein sicherer Nutzer mit Lesezugriff
CREATE USER catalyst_ro PASSWORD '<generated>';
GRANT USAGE ON SCHEMA sales TO catalyst_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA sales TO catalyst_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA sales
GRANT SELECT ON TABLES TO catalyst_ro;
Die Zeile mit den Default Privileges zählt hier genauso viel wie in Postgres: Tabellen, die das ETL von morgen neu erzeugt, sind für den Validierungsnutzer sonst unsichtbar, und Prüfungen scheitern plötzlich mit Berechtigungsfehlern, die sich wie Datenfehler lesen.
Danach isolieren Sie den Workload:
-- In the WLM configuration, give the validation user group its own queue with
-- low concurrency, and a query monitoring rule that aborts on long runtime.
CREATE GROUP validators WITH USER catalyst_ro;
Von Ad-hoc-SQL zum Data Contract
Die Erwartungen zu deklarieren macht sie nachvollziehbar, portabel und unabhängig davon, welches Tool die Tabelle lädt. Catalyst nutzt den Open Data Contract Standard:
apiVersion: v3.0.0
kind: DataContract
info:
title: orders
version: 1.3.0
owner: data-platform
schema:
- name: orders
physicalName: orders
physicalType: table
properties:
- name: order_id
logicalType: string
physicalType: varchar(36)
required: true
primaryKey: true
quality:
- rule: nullCount
dimension: completeness
severity: error
mustBe: "0"
- rule: duplicateCount
dimension: uniqueness
severity: error
mustBe: "0"
- name: customer_id
logicalType: string
quality:
- rule: referentialIntegrity
dimension: consistency
severity: error
mustBe: "customers.id"
- name: status
logicalType: string
quality:
- rule: validValues
dimension: conformity
severity: error
mustBe: "['pending', 'paid', 'shipped', 'refunded']"
- name: total_amount
logicalType: number
physicalType: numeric(12,2)
quality:
- rule: between
dimension: accuracy
severity: error
mustBe: "[0, 100000]"
- name: reference
logicalType: string
quality:
- rule: regex
dimension: conformity
severity: warning
mustBe: "'^ORD-[0-9]{6}#39;"
- name: created_at
logicalType: timestamp
quality:
- rule: freshness
dimension: timeliness
severity: error
mustBe: "<= 24h"
quality:
- rule: rowCount
dimension: consistency
severity: warning
mustBe: "> 0"
Catalyst importiert die Spalten aus information_schema, schlägt einen Basis-Contract vor, kompiliert jede Regel zu Redshift-SQL und hält pro Prüfung pass, warn oder fail fest, samt einer Stichprobe der fehlerhaften Zeilen. Das YAML läuft verlustfrei durch den visuellen Builder — Kommentare und Reihenfolge bleiben erhalten —, sodass die Datei, die im Pull Request geprüft wird, auch die Datei ist, die ausgeführt wird.
Redshift-Stolperfallen, die man kennen sollte
| Falle | Was passiert | Was zu tun ist |
|---|---|---|
Nicht durchgesetzter PRIMARY KEY | Planner vertraut ihm, liefert falsche Ergebnisse | Immer eine duplicateCount-Regel ergänzen |
Nicht durchgesetzter FOREIGN KEY | Verwaiste Zeilen nach Teil-Backfills | Eine referentialIntegrity-Regel ergänzen |
| Geteilte WLM-Queue | Prüfungen konkurrieren mit dem ETL | Eigene Queue + Query Monitoring Rule |
| Veraltete Statistiken | Aggregat wird zum Broadcast Join | Nach ANALYZE validieren |
VARCHAR-Längen in Bytes | Mehrbyte-Text wird beim Laden abgeschnitten | Textspalten großzügig dimensionieren |
Kein ALTER DEFAULT PRIVILEGES | Neue Tabellen sind morgen nicht lesbar | Default-Rechte auf dem Schema vergeben |
GETDATE() liefert UTC | Gegenteil von SQL Server | Alles in UTC halten |
| Late-Binding-Views | Prüfung scheitert, wenn die Basistabelle entfällt | Basistabellen validieren, nicht Views |
Zeitplanung und Alerting
Stoßen Sie die Validierung aus dem Abschluss des COPY oder des Transformationsjobs an, nach ANALYZE, statt von einer festen Uhrzeit aus. Auf Redshift Serverless gilt derselbe Rat mit einem zusätzlichen Anreiz: Ungenutzte Kapazität kostet nichts, aber ein Validierungsdurchlauf, der die Workgroup alle fünfzehn Minuten weckt, hält sie warm — und in der Abrechnung.
Alarmieren Sie auf Übergänge statt auf Dauerzustände, und differenzieren Sie den Schweregrad so, dass error den Prüfungen vorbehalten bleibt, die nachgelagerte Konsumenten wirklich blockieren sollten. Die Eindeutigkeitsregel gehört in Redshift fast immer auf error — angesichts dessen, was ein nicht durchgesetzter Primärschlüssel mit der Korrektheit von Abfragen anstellt.
Häufige Fragen
Setzt Redshift Primärschlüssel durch?
Nein. PRIMARY KEY, UNIQUE und FOREIGN KEY werden akzeptiert und festgehalten, beim Schreiben aber nie durchgesetzt. Der Query Planner vertraut ihnen allerdings, was bedeutet, dass ein doppelter Schlüssel eine Abfrage zu falschen Ergebnissen führen kann — nicht nur zu zusätzlichen Zeilen. Eindeutigkeit mit einer expliziten Prüfung zu validieren ist die einzige verfügbare Durchsetzung.
Kann ich Redshift-Daten validieren, ohne SQL zu schreiben?
Ja. Deklarieren Sie die Erwartung — Pflichtfeld, eindeutig, erlaubte Werte, numerischer Bereich, Regex, Höchstalter, Fremdschlüssel — und lassen Sie das Tool sie zu Redshift-SQL kompilieren. Catalyst importiert das Schema aus information_schema, schlägt einen Satz Basisregeln vor und hält handgeschriebenes SQL für wirklich maßgeschneiderte Logik über eine customSql-Regel bereit.
Wie verhindere ich, dass Validierungsabfragen mein ETL ausbremsen?
Stecken Sie den Validierungsnutzer in eine eigene WLM-Queue mit niedriger Nebenläufigkeit und einer Query Monitoring Rule, die lang laufende Abfragen abbricht, und planen Sie die Prüfungen im Anschluss an den Ladelauf statt parallel dazu. Halten Sie die Prüfungen spaltenbezogen — Redshift ist spaltenorientiert, ein Aggregat über eine einzelne Spalte ist also dramatisch billiger als alles, was die ganze Zeile anfasst.
Funktioniert das mit Redshift Serverless und Redshift Spectrum?
Redshift Serverless verhält sich für alles in diesem Leitfaden identisch; der einzige Unterschied ist die Abrechnung, vermeiden Sie also Zeitpläne, die die Workgroup unnötig wach halten. Externe Spectrum-Tabellen lassen sich problemlos validieren, aber es gibt keinen lokalen Speicher und keinen Sort Key, den man ausnutzen könnte — jede Prüfung scannt also die zugrunde liegenden S3-Objekte. Grenzen Sie sie auf eine Partition ein.
Welche Berechtigungen braucht ein Validierungstool?
USAGE auf dem Schema und SELECT auf den Tabellen, dazu Default Privileges, damit künftige Tabellen das Recht erben. Schreibzugriff ist nicht erforderlich. Catalyst verbindet sich read-only und speichert nur Metadaten und Prüfergebnisse.