Funzioni definite dall'utente (UDF) di SQL e Python in Unity Catalog

Importante

Questa funzionalità è disponibile in anteprima pubblica.

Le funzioni definite dall'utente (UDF) nel catalogo Unity estendono le funzionalità SQL e Python in Azure Databricks. Consentono di definire, usare e condividere e gestire in modo sicuro le funzioni personalizzate in ambienti di elaborazione.

Le funzioni Python UDF registrate come funzioni nel Catalogo Unity differiscono nell'ambito e nel supporto dalle UDF di PySpark con ambito a un notebook o SparkSession. Vedi funzioni scalari Python definite dall'utente (UDF).

Per registrare funzioni definite dall'utente (UDF) scritte in Scala o Java in Unity Catalog, consulta Funzioni definite dall'utente (UDF) in Scala e Java in Unity Catalog.

Per informazioni di riferimento complete sul linguaggio SQL, vedere CREATE FUNCTION (SQL, Python, Scala e Java).

Requisiti

Per usare funzioni definite dall'utente nel Catalogo Unity, è necessario soddisfare i seguenti requisiti:

  • Per usare il codice Python nelle funzioni definite dall'utente registrate nel Catalogo Unity, è necessario usare un SQL Warehouse serverless o pro, o un cluster che esegue Databricks Runtime 13.3 LTS o versione successiva.
  • Se una vista include una funzione definita dall'utente Python del catalogo Unity, l'operazione ha esito negativo nei warehouse SQL classici.
  • Il supporto dell'istanza ARM per le funzioni definite dall'utente in Scala nei cluster abilitati per il "Catalogo Unity" è disponibile in Databricks Runtime 15.2 e versioni successive.

Creazione di funzioni definite dall'utente (UDF) SQL e Python in Unity Catalog

Per creare una UDF SQL o Python in Unity Catalog, gli utenti devono disporre delle autorizzazioni USAGE e CREATE per lo schema e dell'autorizzazione USAGE per il catalogo. Per altri dettagli, vedere del catalogo Unity.

Per eseguire una funzione definita dall'utente (UDF), gli utenti devono disporre dell'autorizzazione EXECUTE sulla UDF. Gli utenti necessitano anche dell'autorizzazione USAGE per lo schema e il catalogo.

Per creare e registrare una UDF in uno schema di Unity Catalog, il nome della funzione deve seguire il formato catalog.schema.function_name. In alternativa, è possibile selezionare il catalogo e lo schema corretti nell'editor SQL. In questo caso, il nome della funzione non deve essere preceduto da catalog.schema:

Creazione di una funzione definita dall'utente con il catalogo e lo schema pre-selezionati.

Nell'esempio seguente viene registrata una nuova funzione nello my_schema schema nel my_catalog catalogo:

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

Le UDF Python per Unity Catalog utilizzano istruzioni delimitate da doppi segni di dollaro ($$). È necessario specificare un mapping dei tipi di dati. L'esempio seguente registra una funzione definita dall'utente che calcola l'indice di massa corporea:

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)
$$;

È ora possibile usare questa funzione del catalogo Unity nelle query SQL o nel codice PySpark:

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

Per altri esempi di funzioni definite dall'utente (UDF), vedere Esempi di filtri di riga ed Esempi di maschera di colonna.

Ampliare le funzioni definite dall'utente utilizzando dipendenze personalizzate

Importante

Questa funzionalità è disponibile in anteprima pubblica.

Per installare dipendenze personalizzate da Internet su un SQL warehouse serverless, l'area di lavoro deve avere abilitata nella pagina Anteprime la funzionalità di anteprima pubblica Attiva la rete per i carichi di lavoro isolati nei SQL warehouse serverless.

È possibile estendere le funzionalità delle UDF Python di Unity Catalog oltre l'ambiente Databricks Runtime specificando dipendenze personalizzate per librerie esterne.

Requisiti

Le dipendenze personalizzate per le UDF del Unity Catalog sono supportate nei tipi di calcolo seguenti:

  • Serverless notebook e attività
  • Calcolo all-purpose classico con Databricks Runtime versione 16.2 e successive
  • Pro o serverless SQL Warehouse

Origini di dipendenza

Installare le dipendenze dalle seguenti fonti.

  • Pacchetti PyPI
  • File archiviati nei volumi di Unity Catalog L'utente che richiama la UDF deve disporre READ VOLUME delle autorizzazioni per il volume di origine.
  • File disponibili negli URL pubblici Le regole di sicurezza della rete dell'area di lavoro devono consentire l'accesso agli URL pubblici. Vedere Requisiti.

Nota

Se l'area di lavoro limita l'accesso alla rete serverless, è necessario configurare le regole di sicurezza di rete per consentire gli URL pubblici. Vedi Impostare le regole in uscita.

Definire le dipendenze

Utilizzare la sezione ENVIRONMENT della definizione della funzione definita dall'utente per specificare le dipendenze:

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 = '3'
)
AS $$
import simplejson as json
import custom_package
return json.dumps(custom_package.process(data))
$$;

La ENVIRONMENT sezione contiene i campi seguenti:

Campo Descrizione TIPO Esempio di utilizzo
dependencies Elenco delle dipendenze separate da virgole da installare. Ogni voce è una stringa conforme al formato di file 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 Specifica la versione dell'ambiente serverless in cui eseguire la UDF (funzione definita dall'utente). Una versione di ambiente fisso esegue l'UDF con una versione di Python specifica e un insieme di pacchetti preinstallati, indipendentemente dalla versione di Python e dai pacchetti nel Databricks Runtime sottostante.
I valori supportati sono None o una versione dell'ambiente 3 o successiva. Le versioni dell'ambiente diverse da None sono supportate solo nelle risorse di calcolo serverless e nei warehouse SQL serverless. Per l'elenco delle versioni disponibili, vedere Versioni dell'ambiente serverless.
STRING environment_version = '3'

Usare le UDF del Catalogo Unity in PySpark

from pyspark.sql.functions import expr

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

Aggiornare una funzione definita dall'utente con ambito sessione

Nota

La sintassi e la semantica per le funzioni definite dall'utente Python nel Unity Catalog differiscono dalle funzioni definite dall'utente Python registrate in SparkSession. Vedere Funzioni scalari definite dall'utente - Python.

Data la funzione definita dall'utente basata su sessione seguente in un notebook di 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()

Per registrare questa operazione come funzione del catalogo Unity, usare un'istruzione SQL CREATE FUNCTION, come nell'esempio seguente:

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

Condividere UDF nel catalogo Unity

I controlli di accesso applicati al catalogo, allo schema o al database in cui viene registrata la UDF ne gestiscono le autorizzazioni. Per altre informazioni, vedere Gestire i privilegi in Unity Catalog .

Usare Azure Databricks SQL o l'interfaccia utente dell'area di lavoro di Azure Databricks per concedere autorizzazioni a un utente o a un gruppo (scelta consigliata).

Autorizzazioni nell'interfaccia utente dell'area di lavoro

  1. Trova il catalogo e lo schema in cui è archiviata la UDF e seleziona l'UDF.
  2. Cercare un'opzione Autorizzazioni nelle impostazioni dell'UDF. Aggiungere utenti o gruppi e specificare il tipo di accesso necessario, ad esempio EXECUTE o MANAGE.

Autorizzazioni nell'interfaccia utente dell'area di lavoro

Autorizzazioni con Azure Databricks SQL

L'esempio seguente concede a un utente l'autorizzazione EXECUTE per una funzione:

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

Per rimuovere le autorizzazioni, usare il comando REVOKE come nell'esempio seguente:

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

Isolamento dell'ambiente

Nota

Gli ambienti di isolamento condiviso richiedono Databricks Runtime 18.0 e versioni successive. Nelle versioni precedenti, tutte le funzioni definite dall'utente Python di Unity Catalog vengono eseguite in modalità di isolamento rigoroso.

Le funzioni definite dall'utente Python del catalogo Unity con lo stesso proprietario e la stessa sessione possono condividere un ambiente di isolamento come impostazione predefinita. Ciò migliora le prestazioni e riduce l'utilizzo della memoria riducendo il numero di ambienti separati che devono essere avviati.

Isolamento rigoroso

Per verificare che una UDF venga sempre eseguita in un ambiente completamente isolato, aggiungere la clausola CHARACTERISTIC STRICT ISOLATION.

La maggior parte delle UDF non richiede un isolamento rigoroso. Le funzioni definite dall'utente per l'elaborazione dati standard traggono vantaggio dall'ambiente predefinito di isolamento condiviso ed eseguono più velocemente con un consumo di memoria inferiore.

Aggiungere la clausola caratteristica alle UDF STRICT ISOLATION che:

  • Eseguire l'input come codice usando eval(), exec()o funzioni simili.
  • Scrivere file nel file system locale.
  • Modificare le variabili globali o lo stato del sistema.
  • Accedere o modificare le variabili di ambiente.

Il codice seguente mostra un esempio di UDF che deve essere eseguita utilizzando STRICT ISOLATION. Questa UDF esegue codice Python arbitrario, quindi potrebbe modificare lo stato del sistema, accedere alle variabili di ambiente o scrivere sul file system locale. L'utilizzo della clausola STRICT ISOLATION aiuta a prevenire interferenze o perdite di dati tra le funzioni definite dall'utente.

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()
$$

Impostare DETERMINISTIC se la funzione produce risultati coerenti

Aggiungere DETERMINISTIC alla definizione della funzione se produce gli stessi output per gli stessi input. Ciò consente alle ottimizzazioni delle query di migliorare le prestazioni.

Per impostazione predefinita, Azure Databricks considera le funzioni definite dall'utente Python (UDF) di Unity Catalog Batch come non deterministiche, a meno che non venga esplicitamente dichiarato il contrario. Esempi di funzioni non deterministiche includono la generazione di valori casuali, l'accesso a date o ore correnti o l'esecuzione di chiamate API esterne.

Vedere CREATE FUNCTION (SQL, Python, Scala e Java)

Funzioni definite dall'utente per gli strumenti dell'agente di intelligenza artificiale

Gli agenti di IA generativa possono usare le UDF di Unity Catalog come strumenti per svolgere attività ed eseguire logiche personalizzate.

Vedere Creare strumenti dell'agente di intelligenza artificiale usando le funzioni del catalogo di Unity.

Funzioni UDF (definite dall'utente) per l'accesso alle API esterne

È possibile usare le funzioni definite dall'utente per accedere da SQL alle API esterne. L'esempio seguente usa la libreria Python requests per effettuare una richiesta HTTP.

Nota

Le UDF Python consentono il traffico di rete TCP/UDP sulle porte 80, 443 e 53 quando si utilizza il calcolo serverless o il calcolo configurato con la modalità di accesso standard.

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

$$;

Funzioni definite dall'utente per la sicurezza e la conformità

Usare le funzioni definite dall'utente Python per implementare tokenizzazione personalizzata, mascheramento dei dati, redazione dei dati o meccanismi di crittografia.

L'esempio seguente maschera l'identità di un indirizzo di posta elettronica mantenendo la lunghezza e il dominio:

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}"
$$

L'esempio seguente applica questa UDF in una definizione di visualizzazione dinamica.

-- 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 |
+---+------------+------------------------+------------------------+

Procedure consigliate

Affinché le funzioni definite dall'utente siano accessibili a tutti gli utenti, Databricks consiglia di creare un catalogo e uno schema dedicati con controlli di accesso appropriati.

Per le funzioni definite dall'utente specifiche del team, usare uno schema dedicato all'interno del catalogo del team per l'archiviazione e la gestione.

Databricks consiglia di includere le informazioni seguenti nella documentazione UDF:

  • Numero di versione corrente
  • Log delle modifiche per tenere traccia delle modifiche tra le versioni
  • Scopo, parametri e valore restituito della funzione definita dall'utente (UDF)
  • Un esempio di come usare la UDF (funzione definita dall'utente)

L'esempio seguente mostra una UDF che segue le buone pratiche:

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)
$$;

Comportamento del fuso orario per gli input timestamp

A partire da Databricks Runtime 18.0, quando si passano i valori TIMESTAMP alle UDF Python, i valori rimangono in UTC. Tuttavia, l'oggetto datetime non include i metadati del fuso orario (tzinfo attributo ).

Questa modifica allinea le UDF Python del catalogo Unity con le UDF Python ottimizzate con Arrow in Apache Spark.

Ad esempio, la query seguente:

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');

In precedenza questo output è stato prodotto nelle versioni di Databricks Runtime precedenti alla 18.0:

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

In Databricks Runtime 18.0 e versioni successive genera ora questo output:

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

Se la UDF dipende dalle informazioni sul fuso orario, è necessario ripristinare esplicitamente tali informazioni:

from datetime import timezone

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

Limiti

  • È possibile definire un numero qualsiasi di funzioni Python all'interno di una funzione definita dall'utente (UDF) di Python, ma tutte queste devono restituire un valore scalare.
  • Le funzioni Python devono gestire i valori NULL in modo indipendente e tutti i mapping dei tipi devono seguire i mapping del linguaggio SQL di Azure Databricks.
  • Se non si specifica un catalogo o uno schema, Azure Databricks registra le funzioni Python definite dall'utente nello schema attualmente attivo.
  • Le UDF Python vengono eseguite in un ambiente sicuro e isolato e non hanno accesso ai file system o ai servizi interni.
  • Non è possibile chiamare più di cinque funzioni definite dall'utente per ogni query.