Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Von Bedeutung
Dieses Feature befindet sich in der Public Preview. Sie können die Vorschauregistrierung auf der Vorschauseite bestätigen. Siehe Verwalten von Azure Databricks-Vorschauen.
Diese Seite zeigt, wie Sie leistungsstarke benutzerdefinierte Funktionen (UDFs) für die Verwendung in ABAC-Zeilenfilter- und Spaltenformatrichtlinien im Unity-Katalog schreiben.
Warum die UDF-Leistung wichtig ist
ABAC-Richtlinien werden für jede Abfrageausführung für jede anwendbare Zeile oder Spalte ausgeführt. Ineffiziente UDFs können:
- Parallele Ausführung und Prädikat-Pushdown blockieren
- Erzwingen teurer Verknüpfungen oder Nachschlagevorgänge pro Zeile
- Erhöhen der Abfragezeit von Millisekunden auf Sekunden (oder mehr)
- Zwischenspeichern und Vektorisierung unterbrechen
- Analyse und Berichterstellung unzuverlässig machen
In Produktionsumgebungen kann dies die Datengovernance zu einem Engpass statt zu einem Enabler machen.
Goldene Regeln für ABAC UDFs
-
Halten Sie es einfach: Bevorzugen Sie grundlegende
CASEAnweisungen und löschen Sie boolesche Ausdrücke. - Bleiben Sie deterministisch: Die gleiche Eingabe sollte immer dieselbe Ausgabe für das Zwischenspeichern und konsistente Verknüpfungen erzeugen.
- Vermeiden Sie externe Aufrufe: keine API-Aufrufe oder Nachschlagevorgänge für andere Datenbanken.
- Verwenden Sie nur integrierte Funktionen in Ihrer UDF: Rufen Sie keine anderen UDFs aus einer UDF auf.
- Test im Maßstab: Überprüfen der Leistung auf mindestens 1 Millionen Zeilen.
- Minimieren Sie komplexität: Vermeiden Sie Schachtelung auf mehreren Ebenen und unnötige Funktionsaufrufe.
- Nur Spaltenverweise: Verweisen Sie nur auf die Spalten der Zieltabelle, um Pushdown zu aktivieren.
-
Bevorzugen Sie SQL vor Python UDFs: für eine bessere Leistung. Wenn Sie Python verwenden müssen, markieren Sie UDFs explizit als
DETERMINISTICwenn sie keine nicht deterministische Logik und Abhängigkeiten beinhalten.
Häufige Antimuster, die vermieden werden sollen
- Externe API-Aufrufe innerhalb von UDFs: verursacht Netzwerklatenz, Timeouts und einzelne Fehlerpunkte.
- Komplexe Unterabfragen oder Verknüpfungen: Erzwingt geschachtelte Schleifenbeitritte und verhindert die Optimierung.
- Schwere Regex auf großem Text: CPU- und arbeitsspeicherintensiv pro Zeile.
-
Metadaten-Nachschlagevorgänge: Vermeiden Sie zeilenspezifische Überprüfungen, die Metadaten oder Identitätsquellen treffen, z
information_schema. B. Abfragen, Benutzerprofil-Nachschlagevorgänge oderis_member()is_account_group_member(). Fügt zusätzliche Scans für jeden Datensatz hinzu. - Dynamische SQL-Generierung: keine Abfrageoptimierung und verhindert zwischenspeichern.
- Nicht deterministische Logik: Verhindert zwischenspeichern und konsistente Verknüpfungen, siehe Auswirkungen nicht deterministischer Logik.
Zugriffsüberprüfungen in Richtlinien beibehalten, nicht UDFs
Ein häufiger Fehler ist das Aufrufen is_account_group_member() oder is_member() direkt innerhalb einer UDF. Dadurch wird die Funktion langsamer und die UDF schwieriger wiederverwendet.
Folgen Sie stattdessen diesem Muster:
- UDF-Rolle: Konzentrieren Sie sich nur auf das Transformieren, Maskieren oder Filtern der Daten. Verwenden Sie nur die darin übergebenen Spalten und Parameter.
- Richtlinienrolle: Definieren Sie, wer (Prinzipale, Gruppen) und wann (Tags) die UDF anwenden soll, indem Sie in der ABAC-Richtlinie auf Prinzipale verweisen.
Auswirkungen nicht deterministischer Logik
Einige Szenarien (z. B. randomisierte Maskierung für Die Forschung) erfordern jedes Mal eine andere Ausgabe.
Wenn Sie nicht deterministische Funktionen verwenden müssen:
- Erwarten Sie eine langsamere Leistung, da keine Zwischenspeicherung auftritt.
- JOINs können fehlschlagen oder inkonsistente Ergebnisse zurückgeben.
- Berichte zeigen möglicherweise unterschiedliche Daten zwischen Denläufen an.
- Die Problembehandlung und Validierung ist möglicherweise schwieriger.
UDF-Beispiele
Nachfolgend finden Sie produktionsfreundliche Muster für Spaltenmasken und Zeilenfilterung. Alle Beispiele folgen den bewährten Methoden für die ABAC-Leistung: einfache Logik, deterministisches Verhalten, keine externen Aufrufe und die Verwendung von nur integrierten Funktionen.
Spaltenmaske: deterministische Pseudonymisierung mit Versionsverwaltung
-- Create a consistent pseudonymized reference ID.
CREATE OR REPLACE FUNCTION mask_id_deterministic(id STRING)
RETURNS STRING
DETERMINISTIC
RETURN CONCAT('REF_', SHA2(CONCAT(id, ':v1'), 256));
Warum dies funktioniert:
- Simple CASE-Anweisung
- Keine externen Abhängigkeiten
- Deterministische Ergebnisse für konsistente Verknüpfungen
- Behält die Prinzipallogik außerhalb der UDF bei
- Behält Verknüpfungen über maskierte Datasets bei
- Enthält ein Versionstag (:v1), um die Schlüsseldrehung zu unterstützen, ohne historische Daten absichtlich zu unterbrechen.
Spaltenmaske: Teilweises Einblenten ohne regex-Hotspots
-- Reveal only the last 4 digits of an SSN, masking the rest.
CREATE OR REPLACE FUNCTION mask_ssn_last4(ssn STRING)
RETURNS STRING
DETERMINISTIC
RETURN CASE
WHEN ssn IS NULL THEN NULL
WHEN LENGTH(ssn) >= 4 THEN CONCAT('XXX-XX-', RIGHT(REGEXP_REPLACE(ssn, '[^0-9]', ''), 4))
ELSE 'MASKED'
END;
Warum dies funktioniert:
- Verwendet ein einzelnes einfaches regex, um Nicht-Ziffern zu entfernen.
- Vermeiden mehrerer Regex-Übergänge für große Textfelder
Zeilenfilter: Pushdown-freundlich nach Region
-- Returns TRUE if the row's state is in the allowed set.
CREATE OR REPLACE FUNCTION filter_by_region(state STRING, allowed ARRAY<STRING>)
RETURNS BOOLEAN
DETERMINISTIC
RETURN array_contains(TRANSFORM(allowed, x -> lower(x)), lower(state));
Warum dies funktioniert:
- Einfache boolesche Logik
- Nur Tabellenspalten verweisen
- Aktiviert prädikatische Pushdown- und Vektorisierung
Zeilenfilter: deterministische Multibedingung
-- Returns TRUE if the row's region is in the allowed set.
CREATE OR REPLACE FUNCTION filter_region_in(region STRING, allowed_regions ARRAY<STRING>)
RETURNS BOOLEAN
DETERMINISTIC
RETURN array_contains(TRANSFORM(allowed_regions, x -> lower(x)), lower(region));
Warum dies funktioniert:
- Unterstützt mehrere Rollen und Regionen in einer Funktion
- Hält Logik flach, um eine bessere Optimierung zu erzielen
Testen der UDF-Leistung
Verwenden Sie synthetische Skalierungstests, um Das Verhalten und die Leistung vor der Produktion zu überprüfen. Beispiel:
WITH test_data AS (
SELECT
patient_id,
your_mask_function(patient_id) as masked_id,
current_timestamp() as start_time
FROM (
SELECT CONCAT('PAT', LPAD(seq, 6, '0')) as patient_id
FROM range(1000000) -- 1 million test rows
)
)
SELECT
COUNT(*) as rows_processed,
MAX(start_time) - MIN(start_time) as total_duration,
COUNT(*) / EXTRACT(EPOCH FROM (MAX(start_time) - MIN(start_time))) as rows_per_second
FROM test_data;
ABAC-Spaltenmaskentypkonvertierung
Databricks wandelt automatisch die Ausgabe von Spaltenmaskenfunktionen um, die aus ABAC-Richtlinien stammen, um dem Datentyp der Zielspalte zu entsprechen. Dadurch wird die Typkonsistenz und das zuverlässige Abfrageverhalten beim Maskieren von Spalten sichergestellt.
Funktionsweise der automatischen Umwandlung
- Richtlinienauswertung: Die ABAC-Richtlinie bestimmt, ob Maskierung angewendet werden soll.
- Ausführung der Maskierungsfunktion: Wenn die Maskierung erforderlich ist, wird die Maskenfunktion ausgeführt.
- Automatische Umwandlung: Das Ergebnis der Maskenfunktion wird automatisch in den Datentyp der Zielspalte umgewandelt.
- Ergebnisrückgabe: Das ordnungsgemäß eingegebene Ergebnis wird an die Abfrage zurückgegeben.
Das gesamte Umwandlungsverhalten folgt ANSI SQL-Standards für CAST Vorgänge. Vollständige Kompatibilitätsdetails finden Sie unter "Returns".
Bewährte Methoden für typsichere Maskierung
Befolgen Sie diese Muster, um sicherzustellen, dass Ihre Maskenfunktionen zuverlässig mit automatischer Typwandlung funktionieren und um Laufzeitfehler zu vermeiden.
Typ-konsistente Maskenfunktionen entwerfen
Stellen Sie sicher, dass Maskenfunktionen Typen zurückgeben, die mit Zielspalten kompatibel sind:
-- Successful: Returns same type as target column
CREATE FUNCTION safe_salary_mask(salary DOUBLE, user_role STRING)
RETURNS DOUBLE
RETURN CASE
WHEN user_role IN ('admin', 'hr') THEN salary
WHEN user_role = 'manager' THEN ROUND(salary / 1000) * 1000
ELSE 0.0
END;
-- Unsuccessful: Returns different type that might not cast
CREATE FUNCTION risky_salary_mask(salary DOUBLE, user_role STRING)
RETURNS STRING
RETURN CASE
WHEN user_role IN ('admin', 'hr') THEN CAST(salary AS STRING)
ELSE 'CONFIDENTIAL' -- This will fail casting to DOUBLE
END;
Verwenden von VARIANT für flexible Maskierung
Bei komplexen Maskierungsszenarien mit unterschiedlichen Ausgabetypen können Sie VARIANT um verschiedene Datentypen zu unterstützen:
CREATE FUNCTION flexible_mask(data VARIANT)
RETURNS VARIANT
RETURN CASE
WHEN schema_of_variant(data) = 'INT' THEN 0::VARIANT
WHEN schema_of_variant(data) = 'DATE' THEN DATE'1970-01-01'::VARIANT
WHEN schema_of_variant(data) = 'DOUBLE' THEN 0.00::VARIANT
ELSE NULL::VARIANT
END;
Testen mit verschiedenen Datenszenarien
Testen Sie Maskenfunktionen mit unterschiedlichen Datenmustern und Benutzerkontexten vor der Produktionsbereitstellung:
-- Test different access levels using different users/groups
SELECT * FROM sensitive_table;
-- Test casting behavior for different regional scenarios
SELECT CAST(mask_transaction(transaction_info, 'US') AS STRUCT<id INT, amount DOUBLE>);
SELECT CAST(mask_transaction(transaction_info, 'JP') AS STRUCT<id INT, amount DOUBLE>);
SELECT CAST(mask_transaction(transaction_info, 'CN') AS STRUCT<id INT, amount DOUBLE>);
Einschränkungen
Einschränkungen für Zeilendateier und Spaltenmasken finden Sie unter "Einschränkungen".