Använd användardatafunktioner i Fabric Data Warehouse (förhandsgranskning)

gäller för:✅ Warehouse i Microsoft Fabric

Important

Den här funktionen är i förhandsversion.

I Fabric Data Warehouse kan T-SQL-utvecklare anropa Fabric användardatafunktioner från T-SQL-frågor. En T-SQL-proxyfunktion i ett lager anropar den refererade Python-funktionen i ett publicerat användardatafunktionsobjekt.

Använd denna integration för att utöka T-SQL med återanvändbar Python-logik för scenarier såsom:

  • Att använda specialiserade PyPI-paket för rumsliga, numeriska eller data science-arbetsbelastningar.
  • Implementerar anpassad affärslogik i Python.
  • Anropar externa API:er.
  • Interagera med andra Fabric-objekt och Azure-tjänster, såsom lager, sjöhus, SQL-databaser eller en Cosmos-databas.

Diagram som visar hur datalagret interagerar med en Fabric User Data Function genom att anropa en U D F via en proxyfunktion för datalagret.

Den här artikeln visar hur man refererar till en publicerad användardatafunktion från Fabric Data Warehouse och använder den i T-SQL-frågor.

Förutsättningar

För att använda användardatafunktioner från Fabric Data Warehouse behöver du:

Skapa och publicera en användardatafunktion

Innan du kan anropa en användardatafunktion från ett lager, skapa och publicera funktionen i ett användardatafunktionsobjekt. För kompletta steg och exempel på Python-funktioner, se Create a user data functions item i Fabric.

En Python-användardatafunktion som du kan skapa visas i följande exempel:

import fabric.functions as fn

udf = fn.UserDataFunctions()

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

Du använder användardatafunktionen item name för att binda en T-SQL-proxyfunktion till Python-funktionen.

Skapa en T-SQL-proxyfunktion

Skapa en T-SQL-funktion i ditt lager och bind den till den publicerade Python-funktionen genom att använda klausulenAS EXTERNAL FUNCTION.

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

Ersätt FunctionSetName med namnet på ditt användardatafunktionsobjekt och ersätt hello_fabric med namnet på den publicerade Python-funktionen.

Tips/Råd

Du kan generera anropskoden från användardatafunktionerna och använda den som utgångspunkt för warehouse-proxyfunktionen.

Som standard härleder CREATE FUNCTION-satsen parameterlistan och returtypen från definitionen av den fjärrstyrda Fabric User Data Function (UDF). Du kan åsidosätta den härledda returtypen genom att specificera den explicit i funktionsdefinitionen. Att ange returtypen är användbart när du vill exponera en mer exakt returtyp än den typ som härleds från den fjärrfunktionella metadatan.

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

Till exempel härleds ett Python-returvärde str vanligtvis som VARCHAR(MAX), men om funktionen alltid returnerar ett värde med en känd maximal längd kan du explicit definiera returtypen som VARCHAR(100) eller en annan lämplig längd för att ge mer exakt metadata och typinformation.

Använd proxyfunktioner i T-SQL-frågor

Efter att du skapat proxyfunktionen, kalla den från T-SQL som vilken annan användardefinierad funktion som helst.

Använd proxyfunktionen i frågeuttryck såsom:

  • SELECT listor.
  • WHERE klausuler.
  • GROUP BY klausuler.
  • Uttryck i UPDATE- och INSERT-satser.

Följande mönster visar hur man anropar en proxyfunktion från en fråga:

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

För avancerade Python-mönster, stödda typer, kopplingar och kontextobjekt, se Fabric användardatafunktionsöversikt.

Konfigurera körning i batchläge

Fabric Data Warehouse kan utföra externa användardatafunktioner i batchläge.

Batch-läge kör flera funktionsanrop i en enda förfrågan till den fjärranslutna Fabric User Data Function (UDF)-tjänsten, vilket minskar nätverksbelastning och förfrågningslatens. En batch kan innehålla upp till 900 funktionsanrop.

Batchläge används vanligtvis när samma funktion tillämpas på värden från en eller flera tabellkolumner, vilket gör att frågeprocessorn kan utvärdera många rader i ett enda fjärranrop istället för att skicka en separat begäran för varje rad. Denna metod kan avsevärt förbättra frågeprestandan, särskilt för stora datamängder och höglatens externa funktionsanrop.

Till exempel, när en fråga applicerar en användardatafunktion på varje värde i en kolumn, kan Fabric Data Warehouse gruppera indatavärdena i batcher och skicka in dem tillsammans för fjärrbearbetning. Den fjärranslutna tjänsten returnerar en motsvarande batch av resultat, som sedan integreras i frågekörningskedjan.

För att aktivera batchläge för en användardatafunktion:

  1. Öppna objektet User data functions .
  2. Gå tillBibliotekshanteringsinställningar>.
  3. Slå på förhandsvisningsfunktioner.

Ställ max_batch_size=900 in i dekoratören @udf.function() för att låta lageret skicka upp till 900 inmatningsrader i varje anrop:

Anmärkning

Argumentet max_batch_size är endast tillgängligt när batch-förhandsvisningen är aktiverad.

import fabric.functions as fn

udf = fn.UserDataFunctions()

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

Efter att du skapat en T-SQL-proxyfunktion som refererar till en batchaktiverad användardatafunktion (UDF), upptäcker Fabric Data Warehouse automatiskt batchkonfigurationen, inklusive den maximala batchstorleken som definieras av fjärrfunktionen. När frågemönstret stödjer batchning grupperar frågeprocessorn flera funktionsanrop i batcher och skickar dem till fjärrtjänsten för exekvering istället för att skicka individuella förfrågningar för varje rad.

Lista användardatafunktioner i ett lager

Användardatafunktioner du skapar med AS EXTERNAL FUNCTION visas i sys.objects med objekttypen XF.

För att lista användardatafunktioner i ett lager, filtrera sys.objects efter type = 'XF'.

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

För att lista både vanliga skalärfunktioner (FN) och användardatafunktioner (XF) tillsammans med deras parameter- och returtypsignaturer, använd sys.parameters och 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

Examples

Följande scenarier visar vanliga sätt att utöka Fabric Data Warehouse med användardatafunktioner.

A. Utöka T-SQL med tolkning av IP-adresser

Använd en Python-användardatafunktion när din lagerförfrågan behöver funktionalitet som inte finns som en inbyggd T-SQL-funktion. Till exempel kan du använda ett IP-adresspaket för att returnera subnätet för en IP-adress. Du kan använda denna funktion i batcher när en fråga bearbetar IP-adresser från många rader. För konfigurationssteg, se Konfigurera batchläge.

Anmärkning

Om funktionen använder ett paket som inte ingår i Python-standardbiblioteket, lägg till paketet i Library Management innan användardatafunktionen publiceras. Detta exempel använder netaddr paketet.

Definiera och publicera Python-funktionen i ett användardatafunktionsobjekt:

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)

Skapa en T-SQL-proxyfunktion i lageret som refererar till den publicerade Python-funktionen:

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

Anropa proxyfunktionen från en lagerförfrågan:

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

Förväntat resultat:192.168.1.0/24

B. Anropa ett externt publikt API

Använd en användardatafunktion när en lagerförfrågan behöver anropa ett externt API som en del av ett databerikningsarbetsflöde.

I SQL Database in Fabric, Azure SQL Database och Azure SQL Managed Instance, sys.sp_invoke_external_rest_endpoint anropar en HTTPS REST-endpoint. I Fabric Data Warehouse kan en användardatafunktion tillhandahålla ett alternativt mönster genom att omsluta ett HTTPS-anrop i Python och exponera det för T-SQL via en proxyfunktion.

Caution

Att anropa en extern endpoint kan överföra data utanför ditt lager. Använd godkända endpoints, undvik att skicka känslig data om det inte är auktoriserat, och följ organisationens säkerhets- och efterlevnadskrav.

Anmärkning

Lägg till nödvändiga tredjepartsbibliotek, såsom requests, i bibliotekshantering innan funktionen publiceras.

Definiera och publicera Python-funktionen i ett användardatafunktionsobjekt. Detta exempel använder parameternamn liknande :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

Skapa en T-SQL-proxyfunktion i lagret:

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

Anropa proxyfunktionen från en lagerförfrågan:

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

C. Använd en konfigurerbar lagringstid

Använd en användardatafunktion när lagerförfrågningar behöver centralt hanterade konfigurationsvärden från ett Fabric-variabelbibliotek. Till exempel, lagra en lagringsperiod i variabelbiblioteket, hämta den via en proxyfunktion och använd den som talargument för DATEADD T-SQL-funktionen.

Innan du publicerar funktionen, lägg till en anslutning från användardatafunktionen i variabelbiblioteket och notera anslutningsaliaset. Variabelbiblioteket i detta exempel innehåller ett RETENTION_DAYS värde som 90.

Definiera och publicera Python-funktionen i ett användardatafunktionsobjekt:

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

Byt ut WarehouseConfig med aliaset för din variabelbiblioteksanslutning.

Skapa en T-SQL-proxyfunktion i lagret:

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

På en persistent T-SQL-anslutning, hämta det konfigurerade värdet en gång och lagra det genom att använda: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;

Värdet förblir tillgängligt under hela sessionens livstid. Hämta den med SESSION_CONTEXT och konvertera den från sql_variant till int innan du använder den med DATEADD och GETDATE. Till exempel, beräkna en retentionsgräns:

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

Återanvänd samma sessionsvärde i en annan sats för att filtrera en tabell:

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

Important

Använd detta mönster från en klient som upprätthåller en persistent T-SQL-anslutning, såsom SQL Server Management Studio eller MSSQL-tillägget för Visual Studio Code. SQL-frågeeditorn i Fabric-portalen har inte stöd för sp_set_session_context, och varje körning använder en separat session. För mer information, se begränsningar för SQL-frågeredigerare.

Felsök användardatafunktioner

Query Insights tillhandahåller den exekverings- och prestandainformation du behöver för att felsöka Fabric-funktioner. Du kan identifiera frågor som anropat en funktion, avgöra om funktionen använde batch- eller radexekvering, och undersöka extern tjänstlatens, omförsök, misslyckade rader och nyttolaststorlek. Använd följande två vyer för att gå från en översikt på frågenivå till detaljerad statistik för varje funktion:

  • Använd queryinsights.exec_requests_history för att identifiera frågor som anropade Fabric- eller AI-funktioner. Vyn inkluderar frågetext, status, inlämningstid och total förfluten tid.
  • Använd queryinsights.external_api_call_stats för att få detaljerad statistik för varje funktion som anropas av en fråga. Vyn inkluderar funktionstyp, exekveringsläge, antal anrop och återförsök, väntetid för externa tjänster, nyttolaststorlek och radresultat.

Vyerna används distributed_statement_id för att identifiera samma frågeexekvering.

Hitta frågor som använde Fabric-funktioner

Använd queryinsights.exec_requests_history för att hitta senaste uttalanden som anropade en Fabric- eller AI-funktion:

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;

Kopiera distributed_statement_id för det påstående som du vill undersöka. Nästa fråga filtrerar de detaljerade statistiken till Fabric-funktioner.

Visa statistik för varje funktion i en sats

Ersätt <distributed_statement_id> med en identifierare som returnerades av föregående fråga. Följande fråga returnerar en rad för varje distinkt Fabric-funktion som anropas av satsen:

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;

Resultaten liknar följande exempel:

function_name körningsläge call_count batch_call_count row_call_count call_retry_count external_service_wait_time_ms genomsnittlig_väntetid_ms_per_anrop rows_total rows_succeeded misslyckade_rader data_sent_bytes mottagna_databyte
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

Felsökningstips

  • Ett högt row_call_count eller ett execution_mode värde på row kan indikera att funktionen inte använder batchexekvering. Om du förväntar dig batchning, bekräfta att batch-lägesförhandsgranskningen är aktiverad och att funktionen använder argumentet max_batch_size .
  • Använd external_service_wait_time_ms och average_wait_time_ms_per_call för att identifiera långsamma yttre reaktioner. Om dessa värden är höga medan data_sent_bytes och data_received_bytes är låga, är responstiden för extern tjänst sannolikt den primära fördröjningen.
  • Stora data_sent_bytes eller data_received_bytes värden kan också öka exekveringstiden. Minska in- eller utdatalasten när funktionen överför mer data än scenariot kräver.