Usar funciones de datos de usuario en Fabric Data Warehouse (vista previa)

Esto se aplica a:✅ Almacén en Microsoft Fabric

Important

Esta característica se encuentra en versión preliminar.

En Fabric Data Warehouse, los desarrolladores de T-SQL pueden invocar funciones de datos de usuario de Fabric en consultas T-SQL. Una función proxy de T-SQL en un almacén llama a la función Python referenciada en un elemento publicado de funciones de datos de usuario.

Utiliza esta integración para extender T-SQL con lógica Python reutilizable para escenarios como:

  • Utilizar paquetes especializados de PyPI para cargas de trabajo espaciales, numéricas o de ciencia de datos.
  • Implementando lógica de negocio personalizada en Python.
  • Llamando a APIs externas.
  • Interactuar con otros elementos de Fabric y con servicios de Azure, como almacenes de datos, lakehouses, bases de datos SQL o Azure Cosmos DB.

Diagrama de cómo el almacén interactúa con una Función de datos de usuario de Fabric, invocando una U D F a través de una función de proxy del almacén.

Este artículo muestra cómo referenciar una función de datos de usuario publicada desde Fabric Data Warehouse y utilizarla en consultas T-SQL.

Prerequisites

Para utilizar funciones de datos de usuario de Fabric Data Warehouse, necesitas:

Crear y publicar una función de datos de usuario

Antes de poder llamar a una función de datos de usuario desde un almacén, crea y publica la función en un elemento de funciones de datos de usuario. Para pasos completos y funciones de ejemplo en Python, véase Crear un elemento de funciones de datos de usuario en Fabric.

Una función de datos de usuario en Python que podrías crear se muestra en el siguiente ejemplo:

import fabric.functions as fn

udf = fn.UserDataFunctions()

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

Usas el nombre del elemento de la función de datos de usuario para vincular una función proxy de T-SQL a la función Python.

Crear una función proxy de T-SQL

Crea una función T-SQL en tu almacén y enlázala a la función de Python publicada usando la AS EXTERNAL FUNCTION cláusula.

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

Sustituye FunctionSetName por el nombre de la función de datos de usuario y hello_fabric por el nombre de la función Python publicada.

Sugerencia

Puedes generar el código de invocación a partir de la experiencia de las funciones de datos de usuario y usarlo como punto de partida para la función proxy del almacén.

Por defecto, la instrucción CREATE FUNCTION infiere la lista de parámetros y el tipo de retorno a partir de la definición de la función remota de datos de usuario Fabric (UDF). Puedes anular el tipo de retorno inferido especificándolo explícitamente en la definición de la función. Proporcionar el tipo de retorno es útil cuando se quiere exponer un tipo de retorno más preciso que el tipo inferido a partir de los metadatos de la función remota.

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

Por ejemplo, un valor de retorno en Python str suele inferirse como VARCHAR(MAX), pero si la función siempre devuelve un valor con una longitud máxima conocida, puedes definir explícitamente el tipo de retorno como VARCHAR(100) u otra longitud apropiada para proporcionar metadatos e información de tipo más precisa.

Utilizar funciones proxy en consultas T-SQL

Después de crear la función proxy, llámala desde T-SQL como cualquier otra función definida por el usuario.

Utiliza la función proxy en expresiones de consulta como:

  • SELECT listas.
  • WHERE cláusulas.
  • GROUP BY cláusulas.
  • Expresiones en las instrucciones UPDATE y INSERT.

El siguiente patrón muestra cómo llamar a una función proxy desde una consulta:

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

Para patrones avanzados de Python, tipos soportados, conexiones y objetos contextuales, véase la visión general del modelo de programación de funciones de usuario de datos de Fabric.

Configurar la ejecución en modo batch

Fabric Data Warehouse puede ejecutar funciones de datos de usuario externos en modo batch.

La ejecución en modo por lotes envía múltiples invocaciones de funciones en una sola solicitud al servicio remoto Fabric User Data Function (UDF), reduciendo la sobrecarga de red y la latencia de las solicitudes. Un lote puede contener hasta 900 llamadas a funciones.

El modo por lotes se utiliza típicamente cuando se aplica la misma función a valores de una o más columnas de la tabla, permitiendo al procesador de consultas evaluar muchas filas en una sola llamada remota en lugar de emitir una solicitud separada para cada fila. Este método puede mejorar significativamente el rendimiento de las consultas, especialmente para conjuntos de datos grandes y llamadas a funciones externas de alta latencia.

Por ejemplo, cuando una consulta aplica una función de datos de usuario a cada valor de una columna, Fabric Data Warehouse puede agrupar los valores de entrada en lotes y enviarlos juntos para su procesamiento remoto. El servicio remoto devuelve un lote correspondiente de resultados, que luego se integran en la cadena de ejecución de consultas.

Para habilitar el modo batch para una función de datos de usuario:

  1. Abre el elemento de funciones de datos de usuario .
  2. Ve a Configuración de gestión> de bibliotecas.
  3. Activa la función de Vista previa.

Configura max_batch_size=900 en el decorador @udf.function() para permitir que el almacén de datos envíe hasta 900 filas de entrada en cada invocación:

Nota:

El max_batch_size argumento solo está disponible cuando la vista previa en modo batch está activada.

import fabric.functions as fn

udf = fn.UserDataFunctions()

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

Después de crear una función proxy T-SQL que hace referencia a una función de datos de usuario (UDF) habilitada para lotes, Fabric Data Warehouse detecta automáticamente la configuración por lotes, incluyendo el tamaño máximo de lote definido por la función remota. Cuando el patrón de consulta soporta procesamiento por lotes, el procesador de consultas agrupa múltiples invocaciones de funciones en lotes y las envía al servicio remoto para su ejecución en lugar de emitir solicitudes individuales para cada fila.

Listar funciones de datos de usuario en un almacén

Las funciones de datos de usuario que creas con AS EXTERNAL FUNCTION aparecen en sys.objects con el tipo de objeto XF.

Para listar funciones de datos de usuario en un almacén, filtra sys.objects por type = 'XF'.

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

Para listar tanto las funciones escalares regulares (FN) como las funciones de datos de usuario (XF) junto con sus firmas de parámetros y tipos de retorno, use sys.parameters y 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 función proxy de T-SQL depende del elemento de funciones de datos de usuario publicado y del nombre de la función. Si renombras o eliminas la función de Python, actualiza la función proxy del almacén en consecuencia.
  • El modelo de programación de funciones de datos de usuario define los tipos de entrada y salida soportados. Verifica que el parámetro Python y las anotaciones de retorno soporten los valores que pasan tus consultas T-SQL.
  • Las funciones de datos de usuario tienen límites de servicio para el tamaño de la carga útil de la solicitud, el tiempo de espera de ejecución, el tamaño de la respuesta, el tamaño de la biblioteca y la retención de registros. Para los límites actuales, consulte Detalles del servicio y limitaciones de las funciones de datos de usuario de Fabric.
  • Los nombres de parámetros deben usar camelCase e incluir anotaciones de tipo. Las funciones decoradas con @udf.function() también deben especificar un tipo de retorno. Para las reglas sintácticas completas, véase resumen del modelo de programación de funciones de datos de usuario de Fabric.
  • Para funciones de transformación de texto integradas que no requieren código Python personalizado, consulta Usar funciones de IA (vista previa).
  • Las funciones de datos de usuario tienen límites de servicio para el tamaño de la carga útil de la solicitud, el tiempo de espera de ejecución, el tamaño de la respuesta, el tamaño de la biblioteca y la retención de registros. Para los límites actuales, consulte Detalles del servicio y limitaciones de las funciones de datos de usuario de Fabric.
  • Los nombres de parámetros deben usar camelCase e incluir anotaciones de tipo. Las funciones decoradas con @udf.function() también deben especificar un tipo de retorno. Para las reglas sintácticas completas, véase resumen del modelo de programación de funciones de datos de usuario de Fabric.
  • Para funciones de transformación de texto integradas que no requieren código Python personalizado, consulta Usar funciones de IA (vista previa).

Ejemplos

Los siguientes escenarios muestran formas comunes de extender Fabric Data Warehouse con funciones de datos de usuario.

A. Extiende T-SQL con análisis de direcciones IP

Utiliza una función de datos de usuario en Python cuando tu consulta de almacén necesite funcionalidades que no estén disponibles como función T-SQL integrada. Por ejemplo, puedes usar un paquete de direcciones IP para devolver la subred de una dirección IP. Puedes aplicar esta función en lotes cuando una consulta procesa direcciones IP de muchas filas. Para los pasos de configuración, consulta Configurar el modo batch.

Nota:

Si la función utiliza un paquete que no forma parte de la biblioteca estándar de Python, añade el paquete en Gestión de Bibliotecas antes de publicar el elemento de la función de datos de usuario. Este ejemplo utiliza el netaddr paquete.

Define y publica la función Python en un elemento de funciones de datos de usuario:

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)

Crea una función proxy T-SQL en el almacén que haga referencia a la función Python publicada:

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

Llamar a la función de proxy desde una consulta de almacén de datos:

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

Resultado esperado:192.168.1.0/24

B. Invocar una API pública externa

Utiliza una función de datos de usuario cuando una consulta de almacén necesite llamar a una API externa como parte de un flujo de trabajo de enriquecimiento de datos.

En la base de datos SQL en Fabric, Azure SQL Database y Azure SQL Managed Instance, sys.sp_invoke_external_rest_endpoint invoca un endpoint HTTPS REST. En Fabric Data Warehouse, una función de datos de usuario puede proporcionar un patrón alternativo envolviendo una llamada HTTPS en Python y exponiéndola a T-SQL mediante una función proxy.

Caution

Llamar a un punto final externo puede transferir datos fuera de tu almacén. Utiliza endpoints aprobados, evita enviar datos sensibles salvo que se autorice y sigue los requisitos de seguridad y cumplimiento de tu organización.

Nota:

Añadir las bibliotecas de terceros necesarias, como requests, en la gestión de bibliotecas antes de publicar la función.

Define y publica la función Python en un elemento de funciones de datos de usuario. Este ejemplo utiliza nombres de parámetros similares a 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

Crea una función proxy T-SQL en el almacén:

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

Llamar a la función de proxy desde una consulta de almacén de datos:

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

C. Utiliza un periodo de retención configurable

Utiliza una función de datos de usuario cuando las consultas de almacén necesiten valores de configuración gestionados centralmente desde una biblioteca de variables Fabric. Por ejemplo, almacenar un periodo de retención en la biblioteca de variables, recuperarlo a través de una función proxy y usarlo como argumento numérico de la DATEADD función T-SQL.

Antes de publicar la función, añade una conexión desde el elemento de funciones de datos de usuario a la biblioteca de variables y anota el alias de conexión. La biblioteca de variables en este ejemplo contiene un RETENTION_DAYS valor como 90.

Define y publica la función Python en un elemento de funciones de datos de usuario:

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"])

Sustituye WarehouseConfig por el alias de tu conexión de biblioteca variable.

Crea una función proxy T-SQL en el almacén:

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

En una conexión T-SQL persistente, recupera el valor configurado una vez y alárdalo usando 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;

El valor permanece disponible durante toda la vida de la sesión. Recupéralo con SESSION_CONTEXT y conviértelo de sql_variant a int antes de usarlo con DATEADD y GETDATE. Por ejemplo, calcule un límite de retención:

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

Reutiliza el mismo valor de sesión en otra instrucción para filtrar una tabla:

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

Important

Utiliza este patrón de un cliente que mantenga una conexión T-SQL persistente, como SQL Server Management Studio o la extensión MSSQL para Visual Studio Code. El editor de consultas SQL en el portal de Fabric no soporta sp_set_session_context, y cada ejecución utiliza una sesión separada. Para más información, véase limitaciones del editor de consultas SQL.

Solucionar problemas de las funciones de datos de usuario

Query Insights proporciona la información de ejecución y rendimiento que necesitas para solucionar problemas con las funciones de Fabric. Puedes identificar consultas que invocaron una función, determinar si la función usó ejecución por lotes o filas, e investigar la latencia de servicios externos, los intentos, las filas fallidas y el tamaño de la carga útil. Utiliza las siguientes dos vistas para pasar de una visión general a nivel de consulta a estadísticas detalladas para cada función:

  • Úsalo queryinsights.exec_requests_history para identificar consultas que invocaron funciones de Fabric o IA. La vista incluye el texto de la consulta, el estado, el tiempo de envío y el tiempo total transcurrido.
  • Úsalo queryinsights.external_api_call_stats para obtener estadísticas detalladas de cada función invocada por una consulta. La vista incluye el tipo de función, el modo de ejecución, los recuentos de llamadas y reintentos, el tiempo de espera de los servicios externos, el tamaño de la carga útil y los resultados por fila.

Las vistas usan distributed_statement_id para identificar la misma ejecución de consulta.

Encuentra consultas que usaron funciones Fabric

Úsalo queryinsights.exec_requests_history para encontrar sentencias recientes que invocaron una función Fabric o 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;

Copia la distributed_statement_id de la declaración que quieres investigar. La siguiente consulta filtra las estadísticas detalladas a funciones de Fabric.

Ver estadísticas de cada función en una sentencia

Sustituye <distributed_statement_id> por un identificador devuelto por la consulta anterior. La siguiente consulta devuelve una fila para cada función Fabric distinta invocada por la sentencia:

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;

Los resultados se parecen al siguiente ejemplo:

function_name modo_de_ejecución call_count batch_call_count row_call_count conteo_reintentos_llamada external_service_wait_time_ms tiempo_medio_de_espera_ms_por_llamada rows_total filas_correctas filas_fallidas bytes_de_datos_enviados bytes_de_datos_recibidos
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

Sugerencias de solución de problemas

  • Un valor alto de row_call_count o un execution_mode de row puede indicar que la función no está usando ejecución por lotes. Si prevés el procesamiento por lotes, confirma que la vista previa del modo por lotes está activada y que la función utiliza el argumento max_batch_size.
  • Utilice external_service_wait_time_ms y average_wait_time_ms_per_call para identificar respuestas externas lentas. Si estos valores son altos y data_sent_bytesdata_received_bytes son bajos, el tiempo de respuesta del servicio externo probablemente sea el retraso principal.
  • Los valores elevados de data_sent_bytes o data_received_bytes también pueden aumentar el tiempo de ejecución. Reduce la carga útil de entrada o salida cuando la función transfiera más datos de los que requiere el escenario.