Sdílet prostřednictvím


Uživatelem definované funkce (UDF) v katalogu Unity

Důležité

Tato funkce je ve verzi Public Preview.

Uživatelem definované funkce (UDF) v katalogu Unity rozšiřují možnosti SQL a Pythonu v rámci Azure Databricks. Umožňují definovat, používat a bezpečně sdílet a řídit vlastní funkce napříč výpočetními prostředími.

Uživatelem definované funkce (UDF) Pythonu zaregistrované jako funkce v Unity Catalog se liší v rozsahu a podpoře ve srovnání s PySpark UDF, které jsou omezeny na poznámkový blok nebo SparkSession. Viz uživatelem definované skalární funkce – Python.

Kompletní referenční informace k jazyku SQL najdete v (SQL a Python).

Požadavky

Pokud chcete používat funkce definované uživatelem v katalogu Unity, musíte splňovat následující požadavky:

  • Pokud chcete použít kód v Pythonu ve funkcích UDF registrovaných v katalogu Unity, musíte použít bezserverový nebo profesionální SQL Warehouse nebo cluster se systémem Databricks Runtime 13.3 LTS nebo novějším.
  • Pokud pohled obsahuje funkci uživatelem definovanou v Pythonu v katalogu Unity, selže u klasických SQL skladů.

Vytváření uživatelem definovaných funkcí v Unity Catalogu

Pokud chcete vytvořit uživatelem definovanou funkci (UDF) v katalogu Unity, uživatelé potřebují oprávnění USAGE a CREATE ke schématu a oprávnění USAGE k katalogu. Podívejte se na Unity Catalog pro více podrobností.

Aby uživatelé mohli spustit UDF, musí mít oprávnění EXECUTE pro UDF. Uživatelé také potřebují oprávnění USAGE pro schéma a katalog.

Pokud chcete vytvořit a zaregistrovat UDF ve schématu katalogu Unity, název funkce by měl následovat podle formátu catalog.schema.function_name. Případně můžete vybrat správný katalog a schéma v editoru SQL. V tomto případě by název vaší funkce neměl mít catalog.schema před sebou:

Vytvoření uživatelsky definované funkce s předem vybraným katalogem a schématem.

Následující příklad zaregistruje novou funkci do schématu my_schemamy_catalog v katalogu:

CREATE OR REPLACE FUNCTION my_catalog.my_schema.calculate_bmi(weight DOUBLE, height DOUBLE)
RETURNS DOUBLE
LANGUAGE SQL
RETURN
SELECT weight / (height * height);

Pythonové UDF pro Unity Catalog používají příkazy odsazené dvojitými dolarovými znaky ($$). Je nutné zadat mapování datového typu. Následující příklad registruje UDF, který vypočítá index tělesné hmotnosti:

CREATE OR REPLACE FUNCTION my_catalog.my_schema.calculate_bmi(weight_kg DOUBLE, height_m DOUBLE)
RETURNS DOUBLE
LANGUAGE PYTHON
AS $$
return weight_kg / (height_m ** 2)
$$;

Teď můžete použít tuto funkci Katalogu Unity v dotazech SQL nebo kódu PySpark:

SELECT person_id, my_catalog.my_schema.calculate_bmi(weight_kg, height_m) AS bmi
FROM person_data;

Další příklady uživatelsky definovaných funkcí najdete v příkladech filtru řádků a příkladech masky sloupců.

Rozšiřte uživatelské funkce pomocí vlastních závislostí

Důležité

Tato funkce je ve verzi Public Preview.

Rozšiřte funkčnost Python UDF katalogu Unity mimo prostředí Databricks Runtime definováním vlastních závislostí externích knihoven.

Nainstalujte závislosti z následujících zdrojů:

  • Balíčky PyPI
  • Soubory uložené ve svazcích katalogu Unity Uživatel, který vyvolá UDF, musí mít READ VOLUME oprávnění ke zdrojovému svazku.
  • Soubory dostupné na veřejných adresách URL Pravidla zabezpečení sítě pracovního prostoru musí umožňovat přístup k veřejným adresám URL.

Poznámka:

Pokud chcete nakonfigurovat pravidla zabezpečení sítě tak, aby umožňovala přístup k veřejným adresám URL z bezserverového SQL Warehouse, přečtěte si téma Ověření pomocí Databricks SQL.

  • Bezserverové sklady SQL vyžadují, aby funkce Public Preview povolovala sítě pro uživatelem definované uživatelem v bezserverových SQL Warehousech na stránce Preview vašeho pracovního prostoru pro přístup k internetu pro vlastní závislosti.

Vlastní závislosti pro uživatelské funkce v katalogu Unity jsou podporovány na následujících typech výpočetních prostředků:

  • Bezserverové poznámkové bloky a úlohy
  • Univerzální výpočet využívající Databricks Runtime verze 16.2 a vyšší
  • Pro nebo bezserverový SQL Warehouse

Použijte část definice UDF ENVIRONMENT k určení závislostí.

CREATE OR REPLACE FUNCTION my_catalog.my_schema.mixed_process(data STRING)
RETURNS STRING
LANGUAGE PYTHON
ENVIRONMENT (
  dependencies = '["simplejson==3.19.3", "/Volumes/my_catalog/my_schema/my_volume/packages/custom_package-1.0.0.whl", "https://my-bucket.s3.amazonaws.com/packages/special_package-2.0.0.whl?Expires=2043167927&Signature=abcd"]',
  environment_version = 'None'
)
AS $$
import simplejson as json
import custom_package
return json.dumps(custom_package.process(data))
$$;

Oddíl ENVIRONMENT obsahuje následující pole:

Pole Popis Typ Příklad využití
dependencies Seznam závislostí oddělených čárkami, které se mají nainstalovat. Každá položka je řetězec, který se řídí formátem souboru pip requirements. STRING dependencies = '["simplejson==3.19.3", "/Volumes/catalog/schema/volume/packages/my_package-1.0.0.whl"]'
dependencies = '["https://my-bucket.s3.amazonaws.com/packages/my_package-2.0.0.whl?Expires=2043167927&Signature=abcd"]'
environment_version Určuje verzi bezserverového prostředí, ve které se má UDF spustit.
V současné době se podporuje jenom hodnota None .
STRING environment_version = 'None'

Používejte uživatelské funkce katalogu Unity v PySparku

from pyspark.sql.functions import expr

result = df.withColumn("bmi", expr("my_catalog.my_schema.calculate_bmi(weight_kg, height_m)"))
display(result)

Aktualizovat UDF s oborem platnosti pro relaci

Poznámka:

Syntaxe a sémantika uživatelem definovaných funkcí Pythonu v katalogu Unity se liší od funkcí definovaných uživatelem Pythonu registrovaných ve SparkSession. Viz uživatelem definované skalární funkce – Python.

Vzhledem k následující uživatelské funkci definované pro relaci v poznámkovém bloku Azure Databricks:

from pyspark.sql.functions import udf
from pyspark.sql.types import StringType

@udf(StringType())
def greet(name):
    return f"Hello, {name}!"

# Using the session-based UDF
result = df.withColumn("greeting", greet("name"))
result.show()

Pokud chcete tuto funkci zaregistrovat jako funkci Katalogu Unity, použijte příkaz SQL CREATE FUNCTION, jak je znázorněno v následujícím příkladu:

CREATE OR REPLACE FUNCTION my_catalog.my_schema.greet(name STRING)
RETURNS STRING
LANGUAGE PYTHON
AS $$
return f"Hello, {name}!"
$$

Sdílení uživatelem definovaných souborů v katalogu Unity

Oprávnění pro UDF se spravují na základě řízení přístupu použitého v katalogu, schématu nebo databázi, kde je UDF registrován. Další informace najdete v tématu Správa oprávnění v katalogu Unity .

Pomocí azure Databricks SQL nebo uživatelského rozhraní pracovního prostoru Azure Databricks udělte oprávnění uživateli nebo skupině (doporučeno).

Oprávnění v uživatelském rozhraní pracovního prostoru

  1. Vyhledejte katalog a schéma, kde je uložená vaše uživatelsky definovaná funkce, a vyberte tuto funkci.
  2. V nastavení UDF vyhledejte možnost Oprávnění . Přidejte uživatele nebo skupiny a zadejte typ přístupu, který mají mít, například EXECUTE nebo MANAGE.

oprávnění v uživatelském rozhraní pracovního prostoru

Oprávnění pomocí Azure Databricks SQL

Následující příklad uživateli udělí oprávnění EXECUTE pro funkci:

GRANT EXECUTE ON FUNCTION my_catalog.my_schema.calculate_bmi TO `user@example.com`;

Pokud chcete oprávnění odebrat, použijte příkaz REVOKE jako v následujícím příkladu:

REVOKE EXECUTE ON FUNCTION my_catalog.my_schema.calculate_bmi FROM `user@example.com`;

Izolace prostředí

Poznámka:

Sdílená prostředí izolace vyžadují Databricks Runtime 18.0 a vyšší. Ve starších verzích se všechny UDF (uživatelem definované funkce) Pythonu v Unity Catalog spouštějí v přísném režimu izolace.

Uživatelsky definované funkce (UDF) Pythonu v Unity Catalog, které mají stejného vlastníka a relaci, mohou ve výchozím nastavení sdílet izolační prostředí. Tím se zlepší výkon a sníží se využití paměti snížením počtu samostatných prostředí, která je potřeba spustit.

Striktní izolace

Pokud chcete zajistit, aby se funkce definovaná uživatelem vždy spouštěla ve vlastním, plně izolovaném prostředí, přidejte tu charakteristickou klauzuli STRICT ISOLATION.

Většina uživatelsky definovaných funkcí nepotřebuje striktní izolaci. Funkce UDF pro standardní zpracování dat využívají výchozí sdílené izolační prostředí a běží rychleji s nižší spotřebou paměti.

Přidejte charakteristickou klauzuli STRICT ISOLATION do funkcí definovaných uživatelem, které:

  • Spusťte vstup jako kód pomocí funkce eval(), exec()nebo podobné funkce.
  • Zapisujte soubory do místního systému souborů.
  • Upravte globální proměnné nebo stav systému.
  • Přístup k proměnným prostředí nebo jejich úprava

Následující kód ukazuje příklad uživatelsky definované funkce, která by se měla spustit pomocí STRICT ISOLATION. Tento UDF spouští libovolný kód Pythonu, takže může změnit stav systému, přistupovat k proměnným prostředí nebo zapisovat do místního systému souborů. Použití klauzule STRICT ISOLATION pomáhá zabránit rušení nebo úniku dat napříč uživatelsky definovanými funkcemi.

CREATE OR REPLACE TEMPORARY FUNCTION run_python_snippet(python_code STRING)
RETURNS STRING
LANGUAGE PYTHON
STRICT ISOLATION
AS $$
import sys
from io import StringIO

# Capture standard output and error streams
captured_output = StringIO()
captured_errors = StringIO()
sys.stdout = captured_output
sys.stderr = captured_errors

try:
    # Execute the user-provided Python code in an empty namespace
    exec(python_code, {})
except SyntaxError:
    # Retry with escaped characters decoded (for cases like "\n")
    def decode_code(raw_code):
        return raw_code.encode('utf-8').decode('unicode_escape')
    python_code = decode_code(python_code)
    exec(python_code, {})

# Return everything printed to stdout and stderr
return captured_output.getvalue() + captured_errors.getvalue()
$$

Nastavení DETERMINISTIC , pokud vaše funkce vytváří konzistentní výsledky

Přidejte DETERMINISTIC do definice funkce, pokud vytváří stejné výstupy pro stejné vstupy. To umožňuje optimalizaci dotazů zlepšit výkon.

Ve výchozím nastavení se definované uživatelem Pythonu v katalogu Batch Unity předpokládá, že nejsou deterministické, pokud nejsou explicitně deklarovány. Mezi ne deterministické funkce patří generování náhodných hodnot, přístup k aktuálním časům nebo kalendářním datům nebo volání externího rozhraní API.

Viz CREATE FUNCTION (SQL a Python)

Funkce definované uživatelem pro nástroje agenta AI

Generující agenti AI můžou jako nástroje k provádění úloh a spouštění vlastní logiky používat uživatelem definované funkce katalogu Unity.

Viz Vytvoření nástrojů agenta AI pomocí funkcí katalogu Unity.

Uživatelsky definované funkce pro přístup k externím rozhraním API

Můžete použít funkce definované uživatelem k přístupu k externím API z SQL. Následující příklad používá knihovnu Pythonu requests k vytvoření požadavku HTTP.

Poznámka:

Python UDFs umožňují síťový provoz TCP/UDP přes porty 80, 443 a 53 při použití bezserverového výpočetního prostředí nebo výpočetních prostředků nakonfigurovaných ve standardním režimu přístupu.

CREATE FUNCTION my_catalog.my_schema.get_food_calories(food_name STRING)
RETURNS DOUBLE
LANGUAGE PYTHON
AS $$
import requests

api_url = f"https://example-food-api.com/nutrition?food={food_name}"
response = requests.get(api_url)

if response.status_code == 200:
   data = response.json()
   # Assume the API returns a JSON object with a 'calories' field
   calories = data.get('calories', 0)
   return calories
else:
   return None  # API request failed

$$;

Funkce definované uživatelem (UDFs) pro zabezpečení a dodržování předpisů

Pomocí uživatelsky definovaných funkcí v Pythonu můžete implementovat vlastní dělení textu na tokeny, maskování dat, redakci dat nebo šifrovací mechanismy.

Následující příklad maskuje identitu e-mailové adresy při zachování délky a domény:

CREATE OR REPLACE FUNCTION my_catalog.my_schema.mask_email(email STRING)
RETURNS STRING
LANGUAGE PYTHON
DETERMINISTIC
AS $$
parts = email.split('@', 1)
if len(parts) == 2:
  username, domain = parts
else:
  return None
masked_username = username[0] + '*' * (len(username) - 2) + username[-1]
return f"{masked_username}@{domain}"
$$

Následující příklad aplikuje tuto UDF v definici dynamického zobrazení:

-- First, create the view
CREATE OR REPLACE VIEW my_catalog.my_schema.masked_customer_view AS
SELECT
  id,
  name,
  my_catalog.my_schema.mask_email(email) AS masked_email
FROM my_catalog.my_schema.customer_data;

-- Now you can query the view
SELECT * FROM my_catalog.my_schema.masked_customer_view;
+---+------------+------------------------+------------------------+
| id|        name|                   email|           masked_email |
+---+------------+------------------------+------------------------+
|  1|    John Doe|   john.doe@example.com |  j*******e@example.com |
|  2| Alice Smith|alice.smith@company.com |a**********h@company.com|
|  3|   Bob Jones|    bob.jones@email.org |   b********s@email.org |
+---+------------+------------------------+------------------------+

Osvědčené postupy

Aby byly funkce definované uživatelem přístupné všem uživatelům, doporučujeme vytvořit vyhrazený katalog a schéma s příslušnými řízeními přístupu.

Pro uživatelem definované uživatelem pro tým použijte vyhrazené schéma v rámci týmového katalogu pro ukládání a správu.

Databricks doporučuje zahrnout do řetězce dokumentace definované uživatelem následující informace:

  • Číslo aktuální verze
  • Protokol změn pro sledování změn napříč verzemi
  • Účel, parametry a návratová hodnota definované uživatelem
  • Příklad použití uživatelsky definované funkce (UDF)

Tady je příklad uživatelsky definované funkce, která dodržuje osvědčené postupy:

CREATE OR REPLACE FUNCTION my_catalog.my_schema.calculate_bmi(weight_kg DOUBLE, height_m DOUBLE)
RETURNS DOUBLE
COMMENT "Calculates Body Mass Index (BMI) from weight and height."
LANGUAGE PYTHON
DETERMINISTIC
AS $$
 """
Parameters:
calculate_bmi (version 1.2):
- weight_kg (float): Weight of the individual in kilograms.
- height_m (float): Height of the individual in meters.

Returns:
- float: The calculated BMI.

Example Usage:

SELECT calculate_bmi(weight, height) AS bmi FROM person_data;

Change Log:
- 1.0: Initial version.
- 1.1: Improved error handling for zero or negative height values.
- 1.2: Optimized calculation for performance.

 Note: BMI is calculated as weight in kilograms divided by the square of height in meters.
 """
if height_m <= 0:
 return None  # Avoid division by zero and ensure height is positive
return weight_kg / (height_m ** 2)
$$;

Chování časového pásma pro vstupy

V Databricks Runtime 18.0 a novějších, pokud se hodnoty TIMESTAMP předávají uživatelským funkcím Pythonu (UDFs), hodnoty zůstanou v UTC, ale metadata časového pásma (atribut tzinfo) nejsou zahrnuta v objektu datetime.

Tato změna sjednotí uživatelem definované funkce Pythonu v katalogu Unity s funkcemi Pythonu optimalizovanými pomocí Arrow v Apache Spark.

Například následující dotaz:

CREATE FUNCTION timezone_udf(date TIMESTAMP)
RETURNS STRING
LANGUAGE PYTHON
AS $$
return f"{type(date)} {date} {date.tzinfo}"
$$;

SELECT timezone_udf(TIMESTAMP '2024-10-23 10:30:00');

Dříve byl tento výstup vytvořen ve verzích Databricks Runtime před 18.0:

<class 'datetime.datetime'> 2024-10-23 10:30:00+00:00 Etc/UTC

V Databricks Runtime 18.0 a novějších vytvoří tento výstup:

<class 'datetime.datetime'> 2024-10-23 10:30:00+00:00 None

Pokud vaše funkce definovaná uživatelem spoléhá na informace o časovém pásmu, musíte ji explicitně obnovit:

from datetime import timezone

date = date.replace(tzinfo=timezone.utc)

Omezení

  • Můžete definovat libovolný počet Python funkcí v rámci uživatelsky definované funkce Pythonu (UDF), ale všechny musí vrátit skalární hodnotu.
  • Funkce Pythonu musí zpracovávat hodnoty NULL nezávisle a všechna mapování typů musí následovat po mapování jazyka SQL v Azure Databricks.
  • Pokud není zadán žádný katalog nebo schéma, uživatelsky definované funkce v Pythonu se zaregistrují do aktuálního aktivního schématu.
  • Python UDF se spouštějí v zabezpečeném, izolovaném prostředí a nemají přístup k souborovým systémům ani interním službám.
  • Ve vašem dotazu nelze volat více než pět UDF (uživatelských funkcí).