Fonctions définies par l'utilisateur (UDF) SQL et Python dans Unity Catalog
Aperçu
Cette fonctionnalité est en aperçu public.
Les fonctions définies par l'utilisateur (UDF) dans Unity Catalog étendent les capacités SQL et Python au sein de Databricks. Ils vous permettent de définir, d'utiliser, de partager et de gérer en toute sécurité des fonctions personnalisées dans différents environnements informatiques.
Les fonctions UDF Python enregistrées en tant que fonctions dans Unity Catalog diffèrent en termes de portée et de prise en charge des fonctions UDF PySpark limitées à un notebook ou à une SparkSession. Voir les fonctions scalaires définies par l'utilisateur Python (UDF).
Pour enregistrer les UDF écrites en Scala ou en Java dans Unity Catalog, consultez Fonctions définies par l'utilisateur (UDF) Scala et Java dans Unity Catalog.
Consultez la référence linguistique SQL complète (CREATE FUNCTION, SQL, Python, Scala et Java).
Exigences
Pour utiliser des UDF dans Unity Catalog, vous devez remplir les exigences suivantes :
- Pour utiliser du code Python dans les UDF enregistrées dans Unity Catalog, vous devez utiliser un SQL warehouse serverless ou Pro ou un cluster exécutant Databricks Runtime 13.3 LTS ou une version ultérieure.
- Si une vue inclut une UDF Python Unity Catalog, elle échoue sur les SQL Warehouse classiques.
- La prise en charge des instances ARM pour les UDF Scala sur les clusters activés pour Unity Catalog est disponible dans Databricks Runtime 15,2 et versions ultérieures.
Création d'UDF SQL et Python dans Unity Catalog
Pour créer une UDF SQL ou Python dans Unity Catalog, les utilisateurs ont besoin des autorisations USAGE et CREATE sur le schéma, et de l'autorisation USAGE sur le catalogue. Consultez Unity Catalog pour plus de détails.
Pour exécuter une UDF, les utilisateurs ont besoin d'une autorisation EXECUTE sur l'UDF. Les utilisateurs ont également besoin de l'autorisation USAGE sur le schéma et le catalogue.
Pour créer et enregistrer une UDF dans un schéma Unity Catalog, le nom de la fonction doit suivre le format catalog.schema.function_name. Alternativement, vous pouvez sélectionner le catalogue et le schéma corrects dans l'éditeur SQL.
Dans ce cas, le nom de votre fonction ne doit pas être précédé de catalog.schema :

L'exemple suivant enregistre une nouvelle fonction dans le schéma my_schema du catalogue my_catalog :
CREATE OR REPLACE FUNCTION my_catalog.my_schema.calculate_bmi(weight DOUBLE, height DOUBLE)
RETURNS DOUBLE
LANGUAGE SQL
RETURN
SELECT weight / (height * height);
Les UDF Python pour Unity Catalog utilisent des instructions décalées par des doubles signes dollar ($$). Vous devez spécifier un mappage de type de données. L'exemple suivant enregistre une UDF qui calcule l'indice de masse corporelle :
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)
$$;
Vous pouvez maintenant utiliser cette fonction Unity Catalog dans vos requêtes SQL ou votre code PySpark :
SELECT person_id, my_catalog.my_schema.calculate_bmi(weight_kg, height_m) AS bmi
FROM person_data;
Voir les exemples de filtres de ligne et les exemples de masques de colonne pour d'autres exemples d'UDF.
Étendre les UDF à l'aide de dépendances personnalisées
Aperçu
Cette fonctionnalité est en aperçu public.
Pour installer des dépendances personnalisées depuis Internet sur un SQL Warehouse Serverless, votre Workspace doit disposer de la fonctionnalité en Public Preview Activer la mise en réseau pour les charges de travail isolées dans les SQL Warehouses Serverless activée sur la page d'aperçu.
Vous pouvez étendre les capacités des UDF Python Unity Catalog au-delà de l'environnement Databricks Runtime en définissant des dépendances personnalisées pour les bibliothèques externes.
Exigences
Les dépendances personnalisées pour les UDF Unity Catalog sont prises en charge sur les types de compute suivants :
- Notebooks et Jobs Serverless
- Compute classique tout usage utilisant Databricks Runtime version 16.2 et supérieures
- SQL Warehouse Pro ou Serverless
Les SQL warehouses Serverless ne garantissent pas une architecture de CPU spécifique. Un warehouse peut s'exécuter sur aarch64 ou x86_64, et l'architecture peut changer entre les redémarrages. Puisqu'un UDF Python de Unity Catalog peut s'exécuter sur une architecture différente de celle où ses dépendances ont été conçues, ses dépendances doivent prendre en charge toutes les architectures que le compute appelant pourrait utiliser.
Si une dépendance est un Python wheel avec des extensions natives (C), son binaire précompilé est spécifique à l'architecture. Une roue construite pour une seule architecture ne parvient pas à s'installer sur l'autre, renvoyant une erreur ISOLATION_ENVIRONMENT_USER_ERROR.GENERIC. Pour éviter cela, incluez les variantes de roue aarch64 et x86_64 dans dependencies et contraintes à leur architecture respective avec un platform_machine marqueur d'environnement.
Sources de dépendance
Installez les dépendances à partir des sources suivantes :
- packages PyPI
- Fichiers stockés dans les volumes Unity Catalog L'utilisateur appelant l'UDF doit disposer des autorisations
READ VOLUMEsur le volume source. - Fichiers disponibles aux URL publiques Les règles de sécurité réseau de votre Workspace doivent autoriser l'accès aux URL publiques. Consultez Exigences.
Si votre Workspace restreint l'accès réseau serverless, vous devez configurer des règles de sécurité réseau pour autoriser les URL publiques. Voir Définir les règles de sortie.
Définir les dépendances
Utilisez la section ENVIRONMENT de la définition de l’UDF pour spécifier les dépendances :
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 section ENVIRONMENT contient les champs suivants :
Champ | Description | Type | Exemple d’utilisation |
|---|---|---|---|
| Une liste de dépendances séparées par des virgules à installer. Chaque entrée est une chaîne qui est conforme au format de fichier d'exigences pip. |
|
|
| Spécifie la version de l'environnement serverless dans laquelle exécuter l'UDF. Une version d'environnement fixe exécute l'UDF avec une version spécifique de Python et un ensemble de packages préinstallés, indépendamment de la version de Python et des packages du Databricks Runtime sous-jacent. Les valeurs prises en charge sont |
|
|
Utiliser des UDF Unity Catalog dans PySpark
from pyspark.sql.functions import expr
result = df.withColumn("bmi", expr("my_catalog.my_schema.calculate_bmi(weight_kg, height_m)"))
display(result)
Mettre à niveau une UDF à l'étendue de la session
La syntaxe et la sémantique des UDF Python dans Unity Catalog diffèrent de celles des UDF Python enregistrées auprès de la SparkSession. Consultez les fonctions scalaires définies par l'utilisateur – Python.
Étant donné l'UDF basée sur une session suivante dans un notebook 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()
Pour l'enregistrer en tant que fonction Unity Catalog, utilisez une instruction SQL CREATE FUNCTION, comme dans l'exemple suivant :
CREATE OR REPLACE FUNCTION my_catalog.my_schema.greet(name STRING)
RETURNS STRING
LANGUAGE PYTHON
AS $$
return f"Hello, {name}!"
$$
Partager des UDF dans Unity Catalog
Les contrôles d'accès appliqués au catalogue, au schéma ou à la base de données où vous enregistrez l'UDF gèrent ses autorisations. Voir Gérer les privilèges dans Unity Catalog pour plus d'information.
Utilisez Databricks SQL ou l'interface utilisateur du Workspace Databricks pour accorder des autorisations à un utilisateur ou à un groupe (recommandé).
Autorisations dans l'interface utilisateur du workspace
- Trouvez le catalogue et le schéma où votre UDF est stockée et sélectionnez l'UDF.
- Recherchez une option **Autorisations** dans les paramètres UDF. Ajoutez des utilisateurs ou des groupes et spécifiez le type d'accès qu'ils doivent avoir, tel que EXECUTE ou MANAGE.

Autorisations utilisant Databricks SQL
L’exemple suivant octroie à un utilisateur l’autorisation EXECUTE sur une fonction :
GRANT EXECUTE ON FUNCTION my_catalog.my_schema.calculate_bmi TO `user@example.com`;
Pour supprimer les autorisations, utilisez la commande REVOKE comme dans l'exemple suivant :
REVOKE EXECUTE ON FUNCTION my_catalog.my_schema.calculate_bmi FROM `user@example.com`;
Isolation de l'environnement
Les environnements d'isolation partagés nécessitent Databricks Runtime 18.0 et versions ultérieures. Dans les versions précédentes, toutes les UDF Python d'Unity Catalog s'exécutent en mode d'isolation strict.
Les UDF Python de Unity Catalog ayant le même propriétaire et la même session peuvent partager un environnement d’isolation par default. Cela améliore les performances et réduit l’utilisation de la mémoire en réduisant le nombre d’environnements distincts qui doivent être lancés.
Isolement strict
Pour vérifier qu'une UDF s'exécute toujours dans son propre environnement entièrement isolé, ajoutez la clause caractéristique STRICT ISOLATION.
La plupart des UDF n'ont pas besoin d'une isolation stricte. Les UDF de traitement de données standard bénéficient de l'environnement d'isolation partagé default et s'exécutent plus rapidement avec une consommation de mémoire inférieure.
Ajoutez la clause caractéristique STRICT ISOLATION aux UDF qui :
- Exécutez l'entrée en tant que code à l'aide de
eval(),exec()ou de fonctions similaires. - Écrire des fichiers dans le système de fichiers local.
- Modifier les variables globales ou l'état du système.
- Accéder ou modifier les variables d'environnement.
Le code suivant présente un exemple d'UDF qui doit être exécutée à l'aide de STRICT ISOLATION. Cette UDF exécute du code Python arbitraire, elle peut donc modifier l’état du système, accéder aux variables d’environnement ou écrire dans le système de fichiers local. L'utilisation de la clause STRICT ISOLATION permet d'éviter les interférences ou les fuites de données entre les fonctions UDF.
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()
$$
Définissez DETERMINISTIC si votre fonction produit des résultats cohérents
Ajoutez DETERMINISTIC à la définition de votre fonction si elle produit les mêmes sorties pour les mêmes entrées. Cela permet aux optimisations de query d'améliorer les performances.
Par default, Databricks traite les UDF Python de Unity Catalog en mode batch comme non déterministes, sauf si vous déclarez explicitement le contraire. Les exemples de fonctions non déterministes incluent la génération de valeurs aléatoires, l'accès aux heures ou dates actuelles, ou les appels d'API externes.
Voir CREATE FUNCTION (SQL, Python, Scala et Java)
UDF pour les outils d'agent IA
Les agents d'IA génératifs peuvent utiliser les fonctions UDF d'Unity Catalog comme outils pour effectuer des tâches et exécuter une logique personnalisée.
Voir Créer des outils d'agent IA à l'aide des fonctions Unity Catalog.
UDFs pour accéder aux APIs externes
Vous pouvez utiliser des UDF pour accéder aux APIs externes à partir de SQL. L'exemple suivant utilise la bibliothèque Python requests pour effectuer une requête HTTP.
Les UDF Python autorisent le trafic réseau TCP/UDP sur les ports 80, 443 et 53 lors de l'utilisation d'un compute serverless ou d'un compute configuré avec le mode d'accès 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
$$;
UDF pour la sécurité et la conformité
Utilisez les UDF Python pour implémenter des mécanismes personnalisés de tokénisation, de masquage de données, de caviardage de données ou de chiffrement.
L'exemple suivant masque l'identité d'une adresse e-mail tout en conservant la longueur et le domaine :
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'exemple suivant applique cette UDF dans une définition de vue dynamique :
-- 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 |
+---+------------+------------------------+------------------------+
Bonnes pratiques
Pour que les UDF soient accessibles à tous les utilisateurs, Databricks vous recommande de créer un catalogue et un schéma dédiés avec des contrôles d'accès appropriés.
Pour les UDF spécifiques à une équipe, utilisez un schéma dédié au sein du catalogue d'équipe pour le stockage et la gestion.
Databricks vous recommande d'inclure les informations suivantes dans la docstring de l'UDF :
- Le numéro de version actuel
- Un journal des modifications pour suivre les modifications entre les versions
- L'objectif de l'UDF, les paramètres et la valeur de retour
- Un exemple d'utilisation de l'UDF
L’exemple suivant montre une UDF qui suit les meilleures pratiques :
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)
$$;
Comportement du fuseau horaire Timestamp pour les entrées
Dans Databricks Runtime 18.0 ou version ultérieure, lorsque vous passez des valeurs TIMESTAMP aux UDF Python, les valeurs restent en UTC. Cependant, l'objet datetime n'inclut pas les métadonnées de fuseau horaire (attribut tzinfo).
Cette modification aligne les UDF Python de Unity Catalog avec les UDF Python optimisées pour Arrow dans Apache Spark.
Par exemple, la requête suivante :
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');
Produisait auparavant cette sortie dans les versions de Databricks Runtime antérieures à 18.0 :
<class 'datetime.datetime'> 2024-10-23 10:30:00+00:00 Etc/UTC
Dans Databricks Runtime 18.0 et versions supérieures, il produit désormais cette sortie :
<class 'datetime.datetime'> 2024-10-23 10:30:00+00:00 None
Si votre UDF s'appuie sur les information de fuseau horaire, vous devez la restaurer explicitement :
from datetime import timezone
date = date.replace(tzinfo=timezone.utc)
Limitations
- Vous pouvez définir n'importe quel nombre de fonctions Python au sein d'une UDF Python, mais toutes doivent retourner une valeur scalaire.
- Les fonctions Python doivent gérer les valeurs NULL de manière indépendante, et toutes les correspondances de types doivent suivre les correspondances de langage Databricks SQL.
- Si vous ne spécifiez pas de catalogue ou de schéma, Databricks enregistre les UDF Python dans le schéma actif actuel.
- Les UDF Python s'exécutent dans un environnement sécurisé et isolé et n'ont pas accès aux systèmes de fichiers ou aux services internes.
- Vous ne pouvez pas appeler plus de cinq fonctions UDF par query.