Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Uyarı
Bu önemli noktalar, sorgu zamanında UDF'leri yürüten satır filtresi ve sütun maskesi ilkeleri için geçerlidir. GRANT ilkeler (Beta) bunlara tabi değildir. Bkz. Modeller için ABAC GRANT ilkeleri (Beta).
Satır filtresi ve sütun maskesi ilkeleri sorgu zamanında çalışan bir mantık oluşturur, bu nedenle performans ilkelerinizi nasıl tasarladığınıza bağlıdır. Her iş yükü için tek bir doğru yaklaşım yoktur. En iyi yaklaşım veri hacminize, sorgu desenlerinize, kullanıcılarınızın korumalı tablolarla nasıl etkileşimde olduğuna ve istediğiniz maskeleme veya filtreleme davranışına bağlıdır. Aşağıdaki bölümlerde en yaygın performans konuları ele alınmalıdır. İlkelerinizi tasarlarken bunları denetim listesi olarak kullanın ve üretime dağıtmadan önce temsili sorgularla test edin.
Performansa genel bakış
| Değerlendirme | Description |
|---|---|
| UDF karmaşıklığını azaltma | Karmaşık UDF mantığı sorgu performansını engelleyebilir; basit işlevler daha iyi performans gösterir. |
| Sorumluları hedefleme yaklaşımı | Politikanın TO/EXCEPT yan tümcelerinde mi yoksa UDF içinde kimlik işlevlerini kullanarak ilke tabanlı mantığı uygulayıp uygulamayacağınıza karar verin. |
| Deterministik, hata güvenli ifadeleri kullanın | Hatalara neden olabilecek belirleyici olmayan işlevler ve ifadeler, iyileştiricinin sonuçları önbelleğe alma ve işlemleri yeniden sıralama becerisini azaltır. |
| Python UDF'lerinden kaçının | Mümkün olduğunda Python UDF'leri yerine SQL UDF'lerini kullanın. |
| Arama tablolarını küçük tutma | Dış tablolara başvuran UDF'ler, bu tablolar yayın için yeterince küçük olduğunda en iyi performansı gösterir. |
| Korumalı tablolarda şart filtreleme optimizasyonunu anlama | Korumalı tablolara yönelik sorgular, önkoşulların yan etkileri varsa bölüm ayıklama veya sıvı kümelemeden yararlanamayabilir. |
| Mümkün olduğunda sütun maskelerini yeniden kullanma | Tablodaki her ayrı maske ek yük getirir; aynı işlevi sütunlar arasında yeniden kullanarak azaltabilirsiniz. |
| Büyük metin alanlarında düzenli ifadelerle maskelemeden kaçının | Serileştirilmiş belgelerde regex tabanlı maskeleme, altyapıyı her satır için tüm yükü taramaya ve yeniden yazmaya zorlar. |
UDF karmaşıklığını azaltma
ABAC ilkesindeki UDF, sorgu yürütme sırasında her satır (satır filtreleri) veya eşleşen her sütun değeri (sütun maskeleri) için yürütülür. UDF'nin karmaşıklığı sorgu performansını doğrudan etkiler.
Do:
- UDF'leri basit tutun. Temel
CASEdeyimleri ve basit boole ifadelerini tercih edin. - UDF'lerde mümkün olduğunca yalnızca hedef tablo sütunlarına başvurun. Bu, koşul göndermeyi etkinleştirir.
- UDF'nizin dış tablolara başvurması gerekiyorsa, herhangi bir dış başvuruyu dağıtmak için yeterince küçük tutun. Atıfta bulunulan tabloların, politikanın erişim düzeniyle eşleşecek şekilde optimize edilip bölümlendirildiğinden emin olun. Örneğin, bir ilke arama tablosunu kullanıcı adına göre bölümleme.
- Çok seviyeli iç içe yapılar ve gereksiz işlev çağrılarından kaçının. Yerleşik SQL işlevlerini mümkün olduğunca kullanın.
Kaçının:
- Dış API çağrıları veya UDF'lerdeki diğer veritabanlarına yapılan aramalar. Ağ çağrıları ek gecikme süresi ve zaman aşımlarına neden olabilir.
- Büyük tablolarda karmaşık alt sorgular veya birleşimler. Bunlar, yayın karma eklemelerini engeller ve iç içe döngü eklemelerini zorlar.
- Büyük metin alanlarında yoğun regex. Büyük metin alanlarında regex hakkında bilgi için bkz.
- Satır başına meta veri aramaları, örneğin sorgulama
information_schema.
Ana unsurları hedefleme yöntemi
ABAC ilkesi yazarken, asıl tabanlı mantığı ilkenin TO/EXCEPT yan tümcelerinde veya current_user() ve is_account_group_member() gibi kimlik işlevlerini kullanarak UDF'nin içinde nereye uygulayacağınıza karar verirsiniz.
Genel olarak, ilkenin TO/EXCEPT hükümlerini, ilkenin prensipler için geçerli olduğunu tanımlamak amacıyla kullanın. Bu, ilke tanımını daha basit tutar ve UDF veri dönüştürmeye, filtrelemeye veya maskelemeye odaklanır. Muaf kullanıcılar için EXCEPT yan tümcesi, ilkeyi tamamen iptal eder; bu da bu kullanıcılar için UDF yürütmesi yapılmayacağı anlamına gelir.
Politikanın ana cümleleri için koşullu mantık çok karmaşık olduğunda, UDF içindeki kimlik işlevleri olası bir alternatif olabilir. Bu işlevler satır başına değil sorgu analizi sırasında bir kez çözümlenir.
is_account_group_member() gibi kimlik işlevlerine farklı grup argümanları ile yapılan birden çok çağrı tek bir UC API çağrısına neden olur, bu nedenle performans üzerindeki etkisi genellikle minimaldir.
Aşağıdaki UDF, yalnızca sorgu analizi sırasında bir kez çözümlenen kimlik işlevlerine bağlı olduğundan verimlidir:
CREATE OR REPLACE FUNCTION rowfilter()
RETURNS BOOLEAN
RETURN
CASE
WHEN is_account_group_member('auditors') OR is_account_group_member('external-auditors') THEN true
WHEN is_account_group_member('low-privileged') THEN false
WHEN session_user() = 'admin@organization.com' THEN true
ELSE false
END;
Buna karşılık, ek tablo araması gerektiren ikincil bir tablodaki ayrıcalıkları kodladığı için aşağıdaki UDF daha yavaştır:
CREATE OR REPLACE FUNCTION rowfilter()
RETURNS BOOLEAN
RETURN
CASE WHEN EXISTS(SELECT 1 FROM access_lease WHERE user = session_user()) THEN true
ELSE false END;
Deterministik, hata güvenli ifadeler kullanın
İlke UDF'lerinde ve korumalı tablolara yönelik sorgularda hata oluşturamayan belirleyici ifadeler kullanın.
Belirlenimci olmayan işlevler (veya rand()gibi now() aynı giriş için farklı sonuçlar döndüren işlevler), iyileştiricinin sonuçları önbelleğe almasını veya sabit katlama uygulamasını engeller. Hem SQL hem de Python UDF'ler DETERMINISTIC deyiminde CREATE FUNCTION anahtar sözcüğünü destekler. SQL UDF'leri için iyileştirici, işlev gövdesinden otomatik olarak determinizm türetir, ancak bunu açıkça da ayarlayabilirsiniz. Python UDF'ler için iyileştirici işlev gövdesini inceleyemez, bu nedenle bir Python UDF'yi belirleyici olarak açıkça işaretlemek, aynı bağımsız değişkenlere sahip çağrılarda sonuç önbelleğe almayı etkinleştirmek açısından önemlidir.
Girişler geçerli değilse, sıfır paydada ANSI bölme gibi bazı ifadeler hata oluşturur. SQL derleyicisi bu olasılığı algıladığında, sorgu planında filtreler gibi işlemleri gönderemez. Bunun yapılması, filtreleme veya maskeleme etkili olmadan önce değerler hakkındaki bilgileri ortaya koyan hataları tetikleyebilir.
try_divide yerine /, try_cast yerine CAST, ve try_to_number yerine to_number gibi hata açısından güvenli alternatifler kullanın. Başarısızlık durumunda NULL döndürür, bu da iyileştiricinin ifadeleri serbestçe yeniden düzenlemesine ve optimize etmesine olanak tanır.
Python UDF'lerinden kaçının
Mümkün olduğunca ABAC politikalarında Python UDF'lerinden kaçının. Python UDF'lerin ilkelerde kullanılabilmesi için bir SQL UDF içinde kapsüllenmesi gerekir. Optimizasyon aracı onları satır içi veya en iyi duruma getiremediği için ve Python işlevi hedef tablodaki her satır için yürütüldüğünden, SQL UDF'lerine kıyasla genellikle daha yavaştır.
Python UDF kullanımı kaçınılmazsa, sonuç önbelleğe almayı etkinleştirmek için Deterministic, error-safe expressionsDETERMINISTIC şeklinde işaretleme adımlarına bakın.
Arama tablolarını küçük tutma
Yaygın bir desen, erişim haklarını küçük bir arama tablosuyla (örneğin, kullanıcıları izin verilen öncelik düzeylerine eşleyen bir tablo) denetlemektir. Arama tablosu hedef tablodan önemli ölçüde küçükse, iyileştirici alt sorguyu yayın karma birleştirmesine dönüştürür. Arama tablosu her yürütücüye kopyalanır ve bellekte karma harita olarak depolanır ve bu da tablo taraması sırasında hızlı filtrelemeye olanak tanır. Kod örneği için bkz: ABAC ilkesi UDF'lerinde Arama Tabloları.
- Arama tablosu büyükse, optimizasyon aracı daha yavaş olan bir karıştırma birleşimine geri döner.
- Arama koşulu karmaşıksa (basit bir eşitlik denetimi değilse), broadcast join da uygun olmayabilir.
- Yayın karma birleştirmesinde bile, yürütme sırasında her satır karma tablo aramasının maliyetine neden olur.
Korumalı tablolarda sorgu ön işleme anlayışını geliştirme
Koşul gönderimi, altyapının filtre koşullarınızı depolama katmanına ittiği bir performans iyileştirmesidir. Bu, altyapının sorgunuzla eşleşmeyen tüm veri bölümlerini atlayarak G/Ç'yi önemli ölçüde azaltmasına ve yürütmeyi hızlandırmasına olanak tanır.
Satır filtreleri ve sütun maskeleriyle korunan tablolar için bu iyileştirme daha karmaşıktır. Bu, korunan tablolarla ilgili performans sorunlarının en yaygın kaynağıdır ve en zor çözümdür çünkü ilke yazarları kullanıcıların korumalı tablolarda çalıştırdığı sorguları denetleyemez.
Bariyer, SecureView koşul itmesini nasıl etkiler?
Hem ABAC hem de tablo düzeyinde satır filtreleri ve sütun maskeleri , yan etkileri olan önkoşulların ilke sınırı boyunca gönderilmesini önlemek için bir SecureView engel kullanır. Bu, yan kanal veri sızıntılarına karşı koruma sağlar, ancak tam tablo taramalarını zorlayan bölüm ayıklama ve sıvı kümeleme iyileştirmelerini de engelleyebilir. Bu durum, ilke UDF bir sabite true çözümlendiğinde bile geçerlidir (aslında hiçbir satır filtrelenmez). Bir tabloda bir ilkenin bulunması SecureView engelini ortaya çıkarır.
Bariyerden etkilenen filtreler
Genellikle optimizasyon aracı, yalnızca yan etkisiz önermeleri SecureView bariyerinin içinden geçirebilir.
-
Aşağı itildi (hızlı):Basit eşitlik karşılaştırmaları (
WHERE col = 'value') ve temel aralık karşılaştırmaları (WHERE col > 100). Bunlar yan etkisizdir ve veri sızıntısı riski taşımaz. -
Engellendi (daha yavaş): İşlevleri çağıran (
WHERE date_format(col, 'yyyy-MM-dd') = '1995-07-29') veya örtük tür atamaları getiren koşul. Bunlar engelinSecureViewüzerinde tutulur, yani filtreyi uygulamadan önce altyapının tabloyu taraması gerekir.
Aşağıdaki örnekte fark gösterilmektedir. üzerinde o_orderdate bölüm anahtarı olan bir tablo ve date_format kullanarak filtreleyen bir sorgu düşünün:
EXPLAIN SELECT * FROM orders
WHERE date_format(o_orderdate, 'yyyy-MM-dd') = '1995-07-29'
İlke olmadan, koşul, date_format düğümünün içinde PartitionFilters olarak görünür ve bu da bölüm budamanın PhotonScan etkin olduğu anlamına gelir.
+- PhotonScan parquet orders[...]
PartitionFilters: [isnotnull(o_orderdate),
(date_format(cast(o_orderdate as timestamp), yyyy-MM-dd, ...))]
Bir politika (her zaman true döndüren bir politika olsa bile), SecureView bariyeri predikatı engeller. Tarama içinde PhotonFilter kalmak yerine PartitionFilters üstüne taşınır ve bu da tam tablo taramasına neden olur.
+- PhotonFilter (date_format(cast(o_orderdate as timestamp),
yyyy-MM-dd, ...) = 1995-07-29)
+- PhotonSecureView orders
+- PhotonScan parquet orders[...]
PartitionFilters: [isnotnull(o_orderdate)]
Daha basit bir önerme olan WHERE o_orderdate = '1995-07-29''nin yan etkisi yoktur ve SecureView bariyeri varken bile aşağıya doğru geçirilebilir:
+- PhotonSecureView orders
+- PhotonScan parquet orders[...]
PartitionFilters: [isnotnull(o_orderdate),
(o_orderdate = 1995-07-29)]
Mümkün olduğunda korumalı tablolarda basit eşitlik koşullarını kullanın. Muaf kullanıcılar için, EXCEPT ilke yan tümcesini kullanarak SecureView engelini tamamen kaldırın, bu da tam koşul gönderimini geri yükler.
Mümkün olduğunda sütun maskelerini yeniden kullanma
Tek bir tabloya çok sayıda farklı sütun maskesi uygulamak sütun başına maliyeti oluşturur. Yalnızca gerçekten hassas veriler içeren sütunları maskeler.
Birden çok sütun için aynı işlem gerektiğinde (örneğin, NULL ile gizlemek veya sabit bir dizeyle değiştirmek), sütun başına ayrı bir işlev oluşturmak yerine aynı maskeleme işlevini tekrar kullanın.
Azure Databricks, aynı UDF'ye ve aynı bağımsız değişkenlere referans veren ilkeleri aynı etkili maske olarak tanır, bu nedenle fonksiyonları yeniden kullanmak gereksiz ek yükten kaçınır.
Büyük metin alanlarında regex maskelemekten kaçının
regexp_replace bir sütun maskesinin içinde, seri hale getirilmiş bir belge (STRING sütunu olarak depolanan XML veya JSON) içindeki öğeleri gizlemek için kullanıldığında maliyetli olur.
regexp_replace her satır için tam dizeyi gösterir. İyileştirici, STRING sütununu opak bir değer olarak değerlendirir ve belgenin kullanılmayan bölümlerini ayıklamaz. Sorgunun yalnızca birkaç alana ihtiyacı olsa bile altyapı yükün tamamını okur ve yeniden yazar.
-- Expensive: regex masking on serialized XML
CREATE FUNCTION mask_xml_pii(raw_xml STRING)
RETURNS STRING
RETURN CASE
WHEN is_account_group_member('sensitive_data_viewers') THEN raw_xml
ELSE regexp_replace(raw_xml, '<SSN>[^<]*</SSN>', '<SSN>***</SSN>')
END;
Bunun yerine, hassas alanları ayrı bir tabloda yazılan sütunlara dönüştürerek bu skaler sütunlara sütun maskeleri uygulayın. Mask işlevi daha sonra seri hale getirilmiş belgenin tamamı yerine satır başına tek bir küçük değer üzerinde çalışır.
-- Source table stores raw XML as STRING
-- Example XML: <person><SSN>123-45-6789</SSN><name>Alice</name><dob>1990-01-01</dob></person>
-- Recommended: extract fields into a table, then mask scalar values
CREATE TABLE person_data AS
SELECT
id,
xpath_string(raw_xml, 'person/SSN') AS ssn,
xpath_string(raw_xml, 'person/name') AS name,
xpath_string(raw_xml, 'person/dob') AS date_of_birth,
raw_xml
FROM raw_records;
-- Simple scalar mask, applied to each extracted column
CREATE FUNCTION redact(val STRING) RETURNS STRING
RETURN CASE
WHEN is_account_group_member('sensitive_data_viewers') THEN val
ELSE '***'
END;
Verileri XML yerine bir yapı sütunu olarak depolayabiliyorsanız, yapı içindeki tek tek alanları düzenlemek için VARIANT esnek maskeleme kalıbını kullanın. Bkz. VARIANT ile yapı sütunlarını maskeleme.
UDF performansını test edin
Büyük ölçekte test edin
Üretime dağıtmadan önce en az 1 milyon satırda UDF performansını test edin. Yapay ölçek testlerine ek olarak, korunan tabloda beklediğiniz gerçek iş yükünü temsil eden sorgular çalıştırın. İlke işlevlerinizde artımlı değişiklikler yapın ve yalnızca son sürümü test etmek yerine her değişikliğin etkisini ölçün.
WITH test_data AS (
SELECT
id,
your_mask_function(id) AS masked_id,
current_timestamp() AS ts
FROM (
SELECT CONCAT('ID', LPAD(CAST(id AS STRING), 6, '0')) AS id
FROM range(1000000)
)
)
SELECT
COUNT(*) AS rows_processed,
MAX(ts) - MIN(ts) AS total_duration
FROM test_data;
your_mask_function değerini test ettiğiniz UDF ile değiştirin. Politikanın etkisini belirlemek için, sonuçları politika uygulanmadan önce ve sonra karşılaştırın.