Fonctions définies par l'utilisateur (UDF) dans Unity Catalog

Important

Cette fonctionnalité est disponible en préversion publique.

Les fonctions définies par l’utilisateur (UDF) dans le catalogue Unity étendent les fonctionnalités de SQL et Python dans Azure Databricks. Ils permettent aux fonctions personnalisées d’être définies, utilisées et partagées et régies en toute sécurité dans les environnements informatiques.

Les UDF Python enregistrées en tant que fonctions dans Unity Catalog diffèrent en termes de portée et de prise en charge des UDF PySpark étendues à un bloc-notes ou à SparkSession. Voir Fonctions scalaires définies par l'utilisateur – Python.

Consultez CREATE FUNCTION (SQL et Python) pour obtenir des informations de référence complètes sur le langage SQL.

Spécifications

Pour utiliser des fonctions définies par l’utilisateur dans le catalogue Unity, les exigences suivantes doivent être remplies :

  • Pour utiliser du code Python dans des fonctions définies par l’utilisateur (UDF) inscrites dans Unity Catalog, vous devez utiliser un entrepôt SQL serverless ou pro ou un cluster exécutant Databricks Runtime 13.3 LTS ou version ultérieure.
  • Si une vue inclut une UDF UC Python, elle échoue sur SQL Classic Warehouses.

Création de fonctions définies par l’utilisateur dans le catalogue Unity

Pour créer une fonction UDF dans le catalogue Unity, les utilisateurs ont besoin de l’autorisation USAGE et CREATE sur le schéma et l’autorisation USAGE sur le catalogue. Pour plus d’informations, consultez le catalogue Unity.

Pour exécuter une fonction UDF, les utilisateurs ont besoin d’une autorisation EXECUTE sur la fonction UDF. Les utilisateurs ont également besoin d’une autorisation USAGE sur le schéma et le catalogue.

L’exemple suivant inscrit une nouvelle fonction dans le schéma du my_schema catalogue Unity :

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

Les fonctions définies par l’utilisateur Python pour le catalogue Unity utilisent des instructions décalées par des signes de double dollar ($$). Vous devez également spécifier un mappage de type de données. L’exemple suivant enregistre une fonction UDF qui calcule l’index de masse corporelle :

CREATE 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 de catalogue Unity dans vos requêtes SQL ou code PySpark :

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

Utilisation de la fonction UDF du catalogue Unity 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 fonction UDF délimitée à une session

Remarque

La syntaxe et la sémantique des UDF Python dans Unity Catalog diffèrent de celles des UDF Python enregistrées dans SparkSession. Consultez les fonctions scalaires définies par l’utilisateur - Python.

Compte tenu de la fonction UDF basée sur une session suivante dans un notebook 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()

Pour l’inscrire en tant que fonction de catalogue Unity, 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 fonctions définies par l’utilisateur dans le catalogue Unity

Les autorisations pour les fonctions définies par l’utilisateur sont gérées en fonction des contrôles d’accès appliqués au catalogue, au schéma ou à la base de données où l’UDF est inscrite. Pour plus d’informations, consultez le catalogue Unity.

Utilisez Azure Databricks SQL ou l’interface utilisateur de l’espace de travail Azure Databricks pour accorder des autorisations à un utilisateur ou un groupe (recommandé).

Autorisations dans l’interface utilisateur de l’espace de travail

  1. Recherchez le catalogue et le schéma où votre UDF est stocké et sélectionnez la fonction UDF.
  2. Recherchez une option Autorisations dans les paramètres UDF. Ajoutez des utilisateurs ou des groupes et spécifiez le type d’accès dont ils doivent disposer, tels que EXECUTE ou MANAGE.

! [Autorisations dans l’interface utilisateur de l’espace de travail](.. /_static/images/udf/high res udf permission.gif)

Autorisations à l’aide d’Azure Databricks SQL

L’exemple suivant accorde à un utilisateur l’autorisation EXECUTE sur une fonction :

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

Pour supprimer des autorisations, utilisez la REVOKE commande comme dans l’exemple suivant :

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

Meilleures pratiques pour les fonctions définies par l’utilisateur

Pour les fonctions définies par l’utilisateur qui doivent être accessibles à tous les utilisateurs, Databricks recommande de créer un catalogue et un schéma dédiés avec des contrôles d’accès appropriés.

Pour les fonctions définies par l’équipe, utilisez un schéma dédié dans le catalogue de l’équipe pour le stockage et la gestion.

Azure Databricks vous recommande d’inclure les informations suivantes dans la documentation de l’UDF :

  • Numéro de version actuel
  • Journal des modifications pour suivre les modifications entre les versions
  • Objectif, paramètres et valeur de retour de la fonction UDF
  • Exemple d’utilisation de la fonction UDF

Voici un exemple de bonnes pratiques UDF suivantes :

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

Fonctions définies par l’utilisateur pour accéder aux API externes

Vous pouvez utiliser des fonctions définies par l’utilisateur pour accéder aux API externes à partir de SQL. L’exemple suivant utilise la bibliothèque Python requests pour effectuer une requête HTTP.

Remarque

Les fonctions définies par l’utilisateur Python autorisent le trafic réseau TCP/UDP sur les ports 80, 443 et 53 à l’aide du calcul ou du calcul serverless configuré avec le mode d’accès partagé.

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()
   # Assuming the API returns a JSON object with a 'calories' field
   calories = data.get('calories', 0)
   return calories
else:
   return None  # API request failed

$$;

Fonctions définies par l’utilisateur pour la sécurité et la conformité

Utilisez les fonctions définies par l’utilisateur Python pour implémenter des mécanismes de jetons personnalisés, de masquage des données, de réaction des 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
AS $$
parts = email.split('@')
masked_username = username[0] + '*' * (len(username) - 2) + username[-1]
return f"{masked_username}@{domain}"
$$

L’exemple suivant applique cette fonction 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 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 |
+---+------------+------------------------+------------------------+

Limites

  • Vous pouvez définir n’importe quel nombre de fonctions Python au sein d’une fonction UDF Python, mais tous doivent retourner une valeur scalaire.
  • Les fonctions Python doivent gérer les valeurs NULL indépendamment, et tous les mappages de types doivent suivre les mappages de langage SQL Azure Databricks.
  • Vous pouvez importer des bibliothèques Python standard incluses par Azure Databricks, mais vous ne pouvez pas inclure de bibliothèques personnalisées ou de dépendances externes.
  • Si aucun catalogue ou schéma n'est spécifié, les UDF Python sont enregistrées 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.