Utiliser les fonctions de données utilisateur dans Fabric Data Warehouse (aperçu)

S’applique à :✅Entrepôt dans Microsoft Fabric

Important

Cette fonctionnalité est en version préliminaire.

En Fabric Data Warehouse, les développeurs T-SQL peuvent appeler Fabric fonctions de données utilisateur à partir de requêtes T-SQL. Une fonction proxy T-SQL dans un entrepôt appelle la fonction Python référencée dans un élément publié des fonctions de données utilisateur.

Utilisez cette intégration pour étendre T-SQL avec une logique Python réutilisable pour des scénarios tels que :

  • Utilisation de logiciels spécialisés PyPI pour des charges spatiales, numériques ou de science des données.
  • Implémentation d’une logique métier personnalisée en Python.
  • Appel aux API externes.
  • Interagir avec d’autres éléments Fabric et services Azure, tels que des entrepôts, des maisons lacustres, des bases de données SQL ou une base de données Cosmos.

Schéma de la façon dont l’entrepôt interagit avec une fonction de données utilisateur Fabric, invoquant un U D F via une fonction proxy d’entrepôt.

Cet article montre comment référencer une fonction de données utilisateur publiée à partir de Fabric Data Warehouse et l’utiliser dans des requêtes T-SQL.

Prerequisites

Pour utiliser les fonctions de données utilisateur de Fabric Data Warehouse, vous avez besoin de :

Créer et publier une fonction de données utilisateur

Avant de pouvoir appeler une fonction de données utilisateur depuis un entrepôt, créez et publiez la fonction dans un élément de fonction de données utilisateur. Pour des étapes complètes et des fonctions Python d’exemple, voir Créer un élément de fonctions de données utilisateur dans Fabric.

Une fonction de données utilisateur Python que vous pourriez créer est illustrée dans l’exemple suivant :

import fabric.functions as fn

udf = fn.UserDataFunctions()

@udf.function()
def hello_fabric(name: str) -> str:
    # Your function logic here
    return name

Vous utilisez le nom de l’élément de la fonction de données utilisateur pour lier une fonction proxy T-SQL à la fonction Python.

Créer une fonction proxy T-SQL

Créez une fonction T-SQL dans votre entrepôt et liez-la à la fonction Python publiée en utilisant la AS EXTERNAL FUNCTION clause.

CREATE OR ALTER FUNCTION dbo.hello_fabric
AS EXTERNAL FUNCTION FunctionSetName.hello_fabric;

Remplacez FunctionSetName par le nom de votre élément de fonction de données utilisateur, puis hello_fabric par le nom de la fonction Python publiée.

Conseil / Astuce

Vous pouvez générer le code d’invocation à partir de l’expérience des fonctions de données utilisateur et l’utiliser comme point de départ pour la fonction proxy de l’entrepôt.

Par défaut, l’instruction CREATE FUNCTION déduit la liste de paramètres et le type de retour à partir de la définition de la fonction de données utilisateur Fabric (UDF) distante. Vous pouvez outrepasser le type de retour inféré en le spécifiant explicitement dans la définition de la fonction. Fournir le type de retour est utile lorsque vous souhaitez exposer un type de retour plus précis que celui déduit des métadonnées de la fonction distante.

CREATE OR ALTER FUNCTION dbo.hello_fabric
RETURNS VARCHAR(100)
AS EXTERNAL FUNCTION FunctionSetName.hello_fabric;

Par exemple, une valeur de retour en Python str est généralement déduite comme VARCHAR(MAX), mais si la fonction retourne toujours une valeur avec une longueur maximale connue, vous pouvez explicitement définir le type de retour comme VARCHAR(100) ou une autre longueur appropriée afin de fournir des métadonnées et des informations de type plus précises.

Utiliser des fonctions proxy dans les requêtes T-SQL

Après avoir créé la fonction proxy, appelez-la depuis T-SQL comme toute autre fonction définie par l’utilisateur.

Utilisez la fonction proxy dans les expressions de requête telles que :

  • SELECT listes.
  • WHERE clauses.
  • GROUP BY clauses.
  • Expressions dans les instructions UPDATE et INSERT.

Le schéma suivant montre comment appeler une fonction proxy à partir d’une requête :

SELECT dbo.<proxy_function_name>(<arguments>) AS function_result;

Pour les patrons Python avancés, les types supportés, les connexions et les objets contextuels, voir l’aperçu du modèle de programmation des fonctions des données utilisateur Fabric.

Configurer l’exécution en mode batch

Fabric Data Warehouse peut exécuter des fonctions de données utilisateur externes en mode batch.

L’exécution en mode batch envoie plusieurs invocations de fonctions dans une seule requête au service distant Fabric User Data Function (UDF), réduisant ainsi la surcharge réseau et la latence des requêtes. Un lot peut contenir jusqu’à 900 appels de fonction.

Le mode batch est généralement utilisé lorsque la même fonction est appliquée à des valeurs provenant d’une ou plusieurs colonnes de tableau, permettant au processeur de requête d’évaluer de nombreuses lignes dans un seul appel distant au lieu d’émettre une requête séparée pour chaque ligne. Cette méthode peut considérablement améliorer la performance des requêtes, en particulier pour de grands ensembles de données et des appels de fonctions externes à forte latence.

Par exemple, lorsqu’une requête applique une fonction de données utilisateur à chaque valeur d’une colonne, Fabric Data Warehouse peut regrouper les valeurs d’entrée en lots et les soumettre ensemble pour un traitement à distance. Le service distant renvoie un lot correspondant de résultats, qui sont ensuite intégrés dans le pipeline d’exécution des requêtes.

Pour activer le mode batch pour une fonction de données utilisateur :

  1. Ouvrez l’élément des fonctions de données utilisateur .
  2. Va dansles paramètresde gestion> de la bibliothèque.
  3. Activez les fonctions de Prévisualisation.

Définissez max_batch_size=900 dans le décorateur @udf.function() pour permettre à l’entrepôt d’envoyer jusqu’à 900 lignes en entrée à chaque appel :

Note

L’argument max_batch_size n’est disponible que lorsque l’aperçu en mode batch est activé.

import fabric.functions as fn

udf = fn.UserDataFunctions()

@udf.function(max_batch_size=900)
def normalizeText(value: str) -> str:
    return value.strip().lower()

Après avoir créé une fonction proxy T-SQL qui fait référence à une fonction de données utilisateur (UDF) compatible batch, Fabric Data Warehouse détecte automatiquement la configuration batch, y compris la taille maximale de batch définie par la fonction distante. Lorsque le motif de requête supporte le batching, le processeur de requête regroupe plusieurs invocations de fonctions en lots et les envoie au service distant pour exécution au lieu d’émettre des requêtes individuelles pour chaque ligne.

Listez les fonctions de données utilisateur dans un entrepôt

Les fonctions de données d’utilisateur que vous créez avec AS EXTERNAL FUNCTION apparaissent dans sys.objects avec le type d’objet XF.

Pour lister les fonctions de données utilisateur dans un entrepôt, filtrez sys.objects par type = 'XF'.

SELECT SCHEMA_NAME(schema_id) AS schema_name, name, object_id, type, type_desc
FROM sys.objects
WHERE type = 'XF';

Pour lister à la fois les fonctions scalaires régulières (FN) et les fonctions de données utilisateur (XF) ainsi que leurs signatures de paramètre et de type de retour, on utilise sys.parameters et sys.types:

WITH metadata AS
(
    SELECT o.schema_id, o.object_id, o.name, p.parameter_id, p.name AS parameter_name, t.name AS type_name
    FROM sys.objects AS o
    INNER JOIN sys.parameters AS p
        ON p.object_id = o.object_id
    INNER JOIN sys.types AS t
        ON t.user_type_id = p.user_type_id
    WHERE o.type IN ('FN', 'XF')
),
signature AS
(
    SELECT SCHEMA_NAME(schema_id) AS schema_name,
           name,
           ANY_VALUE(
               CASE WHEN parameter_id = 0 THEN type_name END
           ) AS return_type,
           CONCAT(
               SCHEMA_NAME(schema_id),
               '.',
               name,
               '(',
               STRING_AGG(
                   CASE
                       WHEN parameter_id > 0
                       THEN CONCAT(parameter_name, ' ', type_name)
                   END,
                   ', '
               ) WITHIN GROUP (ORDER BY parameter_id),
               ') -> ',
               MAX(CASE WHEN parameter_id = 0 THEN type_name END)
           ) AS signature
    FROM metadata
    GROUP BY schema_id, object_id, name
)
SELECT *
FROM signature;

Remarks

  • La fonction proxy T-SQL dépend de l’élément et du nom de fonction des données utilisateur publiées. Si vous renommez ou supprimez la fonction Python, mettez à jour la fonction proxy de l’entrepôt en conséquence.
  • Le modèle de programmation des fonctions de données utilisateur définit les types d’entrée et de sortie pris en charge. Vérifiez que le paramètre Python et les annotations de retour prennent en charge les valeurs que vos requêtes T-SQL passent.
  • Les fonctions de données utilisateur ont des limites de service pour la taille de la charge utile des requêtes, le délai d’exécution, la taille de la réponse, la taille de la bibliothèque et la conservation des journaux. Pour les limites actuelles, voir Détails du service et limitations des fonctions de données utilisateur Fabric.
  • Les noms des paramètres doivent utiliser camelCase et inclure des annotations de type. Les fonctions décorées de @udf.function() doivent également spécifier un type de retour. Pour les règles syntaxiques complètes, voir l’aperçu du modèle de programmation des fonctions de données utilisateur Fabric.
  • Pour des fonctions de transformation de texte intégrées qui ne nécessitent pas de code Python personnalisé, voir Utiliser les fonctions IA (aperçu).
  • Les fonctions de données utilisateur ont des limites de service pour la taille de la charge utile des requêtes, le délai d’exécution, la taille de la réponse, la taille de la bibliothèque et la conservation des journaux. Pour les limites actuelles, voir Détails du service et limitations des fonctions de données utilisateur Fabric.
  • Les noms des paramètres doivent utiliser camelCase et inclure des annotations de type. Les fonctions décorées de @udf.function() doivent également spécifier un type de retour. Pour les règles syntaxiques complètes, voir l’aperçu du modèle de programmation des fonctions de données utilisateur Fabric.
  • Pour des fonctions de transformation de texte intégrées qui ne nécessitent pas de code Python personnalisé, voir Utiliser les fonctions IA (aperçu).

Examples

Les scénarios suivants montrent des moyens courants d’étendre Fabric Data Warehouse avec les fonctions de données utilisateur.

R : Étendre T-SQL avec l’analyse syntaxique des adresses IP

Utilisez une fonction de données utilisateur Python lorsque votre requête d'entrepôt a besoin d'une fonctionnalité qui n'est pas disponible en tant que fonction T-SQL intégrée. Par exemple, vous pouvez utiliser un package d’adresses IP pour retourner le sous-réseau d’une adresse IP. Vous pouvez appliquer cette fonction par lots lorsqu’une requête traite des adresses IP provenant de nombreuses lignes. Pour les étapes de configuration, voir Configurer le mode batch.

Note

Si la fonction utilise un paquet qui ne fait pas partie de la bibliothèque standard Python, ajoutez le paquet dans la gestion de la bibliothèque avant de publier l'élément de la fonction de données utilisateur. Cet exemple utilise le netaddr package.

Définir et publier la fonction Python dans un élément de fonction de données utilisateur :

from netaddr import IPNetwork
import fabric.functions as fn

udf = fn.UserDataFunctions()

@udf.function(max_batch_size=900)
def ipSubnet(ipAddress: str, prefixLength: int = 24) -> str:
    return str(IPNetwork(f"{ipAddress}/{prefixLength}").cidr)

Créez une fonction proxy T-SQL dans l’entrepôt qui fait référence à la fonction Python publiée :

CREATE OR ALTER FUNCTION dbo.ip_subnet
AS EXTERNAL FUNCTION inet.ipSubnet;

Appelez la fonction proxy depuis une requête d’entrepôt :

SELECT dbo.ip_subnet('192.168.1.25', 24) AS subnet;

Résultat attendu :192.168.1.0/24

B. Invoquer une API publique externe

Utilisez une fonction de données utilisateur lorsqu’une requête d’entrepôt doit appeler une API externe dans le cadre d’un flux de travail d’enrichissement de données.

Dans la base de données SQL dans Fabric, Azure SQL Database et Azure SQL Managed Instance, sys.sp_invoke_external_rest_endpoint un point de terminaison HTTPS REST est invoqué. En Fabric Data Warehouse, une fonction de données utilisateur peut fournir un motif alternatif en enroulant un appel HTTPS dans Python et en l’exposant à T-SQL via une fonction proxy.

Caution

Appeler un point de terminaison externe peut transférer des données en dehors de votre entrepôt. Utilisez des points de terminaison approuvés, évitez d’envoyer des données sensibles sauf autorisation et respectez les exigences de sécurité et de conformité de votre organisation.

Note

Ajoutez les bibliothèques tierces requises, telles que requests, dans la gestion des bibliothèques avant de publier la fonction.

Définir et publier la fonction Python dans un élément de fonction de données utilisateur. Cet exemple utilise des noms de paramètres similaires à sys.sp_invoke_external_rest_endpoint:

import json
import requests
import fabric.functions as fn

udf = fn.UserDataFunctions()

@udf.function()
def invokeExternalRestEndpoint(
    url: str,
    method: str = "GET",
    payload: str | None = None,
    headers: str | None = None,
    timeout: int = 30
) -> str:
    requestHeaders = json.loads(headers) if headers else None
    requestPayload = payload if payload else None

    response = requests.request(
        method=method,
        url=url,
        data=requestPayload,
        headers=requestHeaders,
        timeout=timeout
    )
    response.raise_for_status()
    return response.text

Créez une fonction proxy T-SQL dans l’entrepôt :

CREATE OR ALTER FUNCTION dbo.invoke_external_rest_endpoint
AS EXTERNAL FUNCTION api.invokeExternalRestEndpoint;

Appelez la fonction proxy depuis une requête d’entrepôt :

SELECT dbo.invoke_external_rest_endpoint(
    'https://ipapi.co/8.8.8.8/country_name/',
    'GET',
    NULL,
    NULL,
    30
) AS response;

C. Utiliser une période de rétention configurable

Utilisez une fonction de données utilisateur lorsque les requêtes d’entrepôt nécessitent des valeurs de configuration gérées centralisément à partir d’une bibliothèque de variables Fabric. Par exemple, stocker une période de conservation dans la bibliothèque de variables, la récupérer via une fonction proxy, et l’utiliser comme argument numérique de la DATEADD fonction T-SQL.

Avant de publier la fonction, ajoutez une connexion de l’élément des fonctions de données utilisateur à la bibliothèque de variables et notez l’alias de connexion. La bibliothèque de variables dans cet exemple contient une RETENTION_DAYS valeur telle que 90.

Définir et publier la fonction Python dans un élément de fonction de données utilisateur :

import fabric.functions as fn

udf = fn.UserDataFunctions()

@udf.connection(argName="varLib", alias="WarehouseConfig")
@udf.function()
def getRetentionDays(varLib: fn.FabricVariablesClient) -> int:
    variables = varLib.getVariables()
    return int(variables["RETENTION_DAYS"])

Remplacez-le WarehouseConfig par l’alias de votre connexion à la bibliothèque variable.

Créez une fonction proxy T-SQL dans l’entrepôt :

CREATE OR ALTER FUNCTION dbo.get_retention_days
AS EXTERNAL FUNCTION config.getRetentionDays;

Sur une connexion T-SQL persistante, récupérez la valeur configurée une fois et stockez-la en utilisant sp_set_session_context:

DECLARE @retention_days int = dbo.get_retention_days();

EXECUTE sys.sp_set_session_context
    @key = N'retention_days',
    @value = @retention_days,
    @read_only = 1;

La valeur reste disponible pendant toute la durée de la session. Récupérez-le avec SESSION_CONTEXT et convertissez-le depuis sql_variant vers int avant en l’utilisant avec DATEADD et GETDATE. Par exemple, calculez un seuil de rétention :

SELECT DATEADD(
    day,
    -CONVERT(int, SESSION_CONTEXT(N'retention_days')),
    GETDATE()
) AS retention_cutoff;

Réutilisez la même valeur de session dans une autre instruction pour filtrer une table :

SELECT *
FROM dbo.events
WHERE event_timestamp >= DATEADD(
    day,
    -CONVERT(int, SESSION_CONTEXT(N'retention_days')),
    GETDATE()
);

Important

Utilisez ce schéma d’un client qui maintient une connexion T-SQL persistante, comme SQL Server Management Studio ou l’extension MSSQL pour Visual Studio Code. L'éditeur de requêtes SQL dans le portail Fabric ne prend pas en charge sp_set_session_context, et chaque exécution utilise une session distincte. Pour plus d’informations, voir les limitations de l’éditeur de requêtes SQL.

Résoudre les problèmes liés aux fonctions de données utilisateur

Query Insights fournit les informations d’exécution et de performance nécessaires pour dépanner les fonctions Fabric. Vous pouvez identifier les requêtes qui ont invoqué une fonction, déterminer si la fonction utilisait l’exécution par lots ou par ligne, et enquêter sur la latence des services externes, les retentions, les lignes échouées et la taille de la charge utile. Utilisez les deux vues suivantes pour passer d’un aperçu au niveau de la requête à des statistiques détaillées pour chaque fonction :

  • Utilisez queryinsights.exec_requests_history pour identifier les requêtes qui ont invoqué des fonctions Fabric ou IA. La vue inclut le texte de la requête, le statut, le temps de soumission et le temps total écoulé.
  • Utilisez-le queryinsights.external_api_call_stats pour obtenir des statistiques détaillées pour chaque fonction invoquée par une requête. La vue inclut le type de fonction, le mode d’exécution, le nombre d’appels et de réessays, le temps d’attente du service externe, la taille de la charge utile et les résultats des lignes.

Les vues utilisent distributed_statement_id pour identifier la même exécution de requête.

Trouver les requêtes utilisant des fonctions Fabric

Utilisez queryinsights.exec_requests_history pour trouver des instructions récentes qui ont invoqué une fonction Fabric ou d’IA :

SELECT TOP 100
       h.distributed_statement_id,
       h.submit_time,
       h.status,
       h.total_elapsed_time_ms,
       h.command
FROM queryinsights.exec_requests_history AS h
WHERE h.is_using_external_api = 1
ORDER BY h.submit_time DESC;

Copiez la distributed_statement_id déclaration que vous souhaitez examiner. La requête suivante filtre les statistiques détaillées vers des fonctions Fabric.

Afficher les statistiques pour chaque fonction dans une instruction

Remplacez-le <distributed_statement_id> par un identifiant retourné par la requête précédente. La requête suivante retourne une ligne pour chaque fonction Fabric distincte invoquée par l’instruction :

DECLARE @distributed_statement_id uniqueidentifier =
    '<distributed_statement_id>';

SELECT function_name,
       execution_mode,
       call_count,
       batch_call_count,
       row_call_count,
       call_retry_count,
       external_service_wait_time_ms,
       external_service_wait_time_ms
           / call_count AS average_wait_time_ms_per_call,
       rows_total,
       rows_succeeded,
       rows_failed,
       data_sent_bytes,
       data_received_bytes
FROM queryinsights.external_api_call_stats
WHERE distributed_statement_id = @distributed_statement_id
  AND function_type = 'FABRIC_FUNCTION'
ORDER BY external_service_wait_time_ms DESC;

Les résultats ressemblent à l’exemple suivant :

function_name mode d’exécution call_count batch_call_count nombre_d_appels_de_ligne nombre_de_nouvelles_tentatives_d'appel external_service_wait_time_ms temps_attente_moyen_ms_par_appel rows_total lignes_réussies lignes_échouées données_envoyées_octets données_reçues_en_octets
inet.ipSubnet batch 12 12 0 0 840 70 600 600 0 12,000 9,600
api.invokeExternalRestEndpoint row 4 0 4 1 1,920 480 4 4 0 1,024 512

Conseils de dépannage

  • Une valeur row_call_count élevée ou une valeur execution_mode de row peut indiquer que la fonction n’utilise pas l’exécution par lot. Si vous attendez un traitement par lots, confirmez que l’aperçu en mode batch est activé et que la fonction utilise l’argument max_batch_size .
  • Utilisez external_service_wait_time_ms et average_wait_time_ms_per_call pour identifier les réponses externes lentes. Si ces valeurs sont élevées et data_sent_bytesdata_received_bytes faibles, le temps de réponse du service externe est probablement le principal retard.
  • Les valeurs grandes data_sent_bytesdata_received_bytes peuvent également augmenter le temps d’exécution. Réduisez la charge utile d’entrée ou de sortie lorsque la fonction transfère plus de données que ce que le scénario exige.