Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Gilt für:✅ SQL-Analyseendpunkt und Warehouse in Microsoft Fabric
Microsoft Fabric Data Warehouse verwendet zwei Inline-Techniken, um skalare, benutzerdefinierte Funktionen (UDFs) als Teil verteilter Abfragen auszuführen:
- ExprBlock-Inlining unterstützt berechnungsbasierte skalare UDFs, die in ihren Funktionskörpern keine Daten referenzieren, und unterstützt eine Vielzahl von Aufruf-Abfrage-Formen.
- Das skalare UDF-Inlining in Fabric Data Warehouse (Vorschau) hat strenge Anforderungen sowohl an die Funktionsdefinition als auch an die aufrufende Abfrage. Weitere Informationen zu den beiden Techniken und ihren Anforderungen finden Sie unter CREATE FUNCTION.
Hinweis
Skalare UDFs sind derzeit eine Vorschaufunktion in Fabric Data Warehouse.
In diesem Artikel erfahren Sie, wie man eine nicht inlineable UDF in eine inlineable Funktion umwandelt oder eine nicht-inlineable UDF erstellt.
Machen Sie eine nicht inlinefähige skalare UDF inlinefähig
Die T-SQL-Codeänderungen, die erforderlich sind, um ein skalares UDF inlineable zu machen, hängen davon ab, welches Konstrukt seine Definition nicht-inlineable macht.
Die folgenden Beispiele zeigen, wie mehrere RETURN-Anweisungen, @@ROWCOUNT und eine zeitabhängige Funktion in einer UDF mit Datenzugriff umgeschrieben werden.
Ersetzen Sie mehrere RETURN-Anweisungen
Die folgende Funktion liest den Kundentyp aus einer Tabelle und enthält mehrere RETURN Anweisungen. Da die Funktion auf Tabellendaten zugreift, gelten skalare UDF-Inlining-Anforderungen. Mehrere RETURN Anweisungen machen diese Definition nicht inlinefähig.
Gib WITH INLINE = AUTO an, um die Funktion zu erstellen, während du dich darauf vorbereitest, sie neu zu schreiben:
CREATE OR ALTER FUNCTION dbo.GetDiscount (@CustomerID INT)
RETURNS DECIMAL(5, 2)
WITH INLINE = AUTO
AS
BEGIN
DECLARE @CustomerType VARCHAR(20);
SELECT @CustomerType = CustomerType
FROM dbo.Customer
WHERE CustomerID = @CustomerID;
IF @CustomerType = 'Regular' RETURN 0.05;
IF @CustomerType = 'Premium' RETURN 0.10;
IF @CustomerType = 'VIP' RETURN 0.15;
RETURN 0.01;
END;
GO
Überprüfen Sie, ob die Funktion inlineierbar ist
Die Katalogansicht sys.sql_modules zeigt zwei Eigenschaften, die die skalare UDF-Inlineability beschreiben:
-
is_inlineablegibt an, ob die Funktionsdefinition inlineable ist. Ein Wert von1bedeutet inlineabel, und0bedeutet nicht-inlineabel. -
inline_eligibility_maskidentifiziert, welche Inlining-Technik die Funktionsdefinition verarbeiten kann. Weitere Informationen zu den Werten finden Sie unter Check ob ein skalares UDF inlineiert werden kann.
Verwenden Sie die folgende Abfrage, um dbo.GetDiscount zu überprüfen:
SELECT
SCHEMA_NAME(o.schema_id) AS function_schema,
o.name AS function_name,
m.is_inlineable,
m.inline_eligibility_mask
FROM sys.sql_modules AS m
INNER JOIN sys.objects AS o
ON m.object_id = o.object_id
WHERE o.type = 'FN'
AND SCHEMA_NAME(o.schema_id) = 'dbo'
AND o.name = 'GetDiscount';
GO
Die Metadaten beschreiben die Funktionsdefinition. Für die ursprüngliche Definition von dbo.GetDiscount ist 0is_inlineable.
Schreiben Sie die Funktion um, um das Ergebnis einer lokalen Variablen zuzuweisen, und verwenden Sie eine letzte RETURN Anweisung:
CREATE OR ALTER FUNCTION dbo.GetDiscount (@CustomerID INT)
RETURNS DECIMAL(5, 2)
AS
BEGIN
DECLARE @Discount DECIMAL(5, 2) = 0.01;
SELECT @Discount =
CASE CustomerType
WHEN 'Regular' THEN 0.05
WHEN 'Premium' THEN 0.10
WHEN 'VIP' THEN 0.15
ELSE 0.01
END
FROM dbo.Customer
WHERE CustomerID = @CustomerID;
RETURN @Discount;
END;
GO
Die überarbeitete Funktion hat eine Anweisung RETURN und erfüllt die skalaren UDF-Inlining-Anforderungen. Führe die Metadaten-Abfrage erneut aus, um zu überprüfen, ob is_inlineable1 ist.
Hinweis
ExprBlock-Inlining unterstützt mehrere RETURN-Anweisungen. Dieses Beispiel liest Tabellendaten und verwendet daher skalares UDF-Inlining, das eine einzige RETURN Anweisung erfordert.
Ersetzen Sie @@ROWCOUNT durch einen Anfangswert
Die folgende Datenzugriffs-UDF verwendet @@ROWCOUNT, um zu bestimmen, ob ihre Abfrage einen Kunden gefunden hat.
@@ROWCOUNT wird vom skalaren UDF-Inlining nicht unterstützt, daher ist die Definition nicht inlineierbar:
CREATE OR ALTER FUNCTION dbo.CustomerExists (@CustomerID INT)
RETURNS BIT
WITH INLINE = AUTO
AS
BEGIN
DECLARE @CustomerExists BIT = 1;
SELECT @CustomerExists = 1
FROM dbo.Customer
WHERE CustomerID = @CustomerID;
IF @@ROWCOUNT = 0 SET @CustomerExists = 0;
RETURN @CustomerExists;
END;
GO
Initialisieren Sie die Variable mit dem Ergebnis für den Fall, dass keine übereinstimmende Zeile vorhanden ist.
SELECT ändert den Wert nur, wenn eine Zeile gefunden wird, wodurch es nicht mehr nötig ist, @@ROWCOUNT zu überprüfen:
CREATE OR ALTER FUNCTION dbo.CustomerExists (@CustomerID INT)
RETURNS BIT
AS
BEGIN
DECLARE @CustomerExists BIT = 0;
SELECT @CustomerExists = 1
FROM dbo.Customer
WHERE CustomerID = @CustomerID;
RETURN @CustomerExists;
END;
GO
Führe die Metadatenabfrage aus dem vorherigen Beispiel mit CustomerExists als Funktionsnamen aus. Die Anfangsdefinition hat is_inlineable = 0, und die überarbeitete Definition hat is_inlineable = 1.
Geben Sie einen zeitabhängigen Wert in ein datenzugriffsfähiges UDF ein
Die folgende Funktion kombiniert den Tabellenzugriff mit GETUTCDATE(). Tabellenzugriff erfordert skalare UDF-Inlining, wobei eine zeitabhängige Funktion im UDF-Körper die Definition nicht inlineierbar macht:
CREATE OR ALTER FUNCTION dbo.GetCustomerTenureDays (@CustomerID INT)
RETURNS INT
WITH INLINE = AUTO
AS
BEGIN
DECLARE @MemberSince DATE;
SELECT @MemberSince = MemberSince
FROM dbo.Customer
WHERE CustomerID = @CustomerID;
RETURN DATEDIFF(DAY, @MemberSince, GETUTCDATE());
END;
GO
Geben Sie stattdessen das aktuelle Datum und die Uhrzeit als Parameter in die Funktion ein:
CREATE OR ALTER FUNCTION dbo.GetCustomerTenureDays
(
@CustomerID INT,
@AsOfDate DATETIME2(6)
)
RETURNS INT
AS
BEGIN
DECLARE @MemberSince DATE;
SELECT @MemberSince = MemberSince
FROM dbo.Customer
WHERE CustomerID = @CustomerID;
RETURN DATEDIFF(DAY, @MemberSince, @AsOfDate);
END;
GO
Evaluiere GETUTCDATE() in der aufrufenden Abfrage und übergebe ihren Wert an das UDF:
SELECT
CustomerID,
CustomerName,
dbo.GetCustomerTenureDays(CustomerID, GETUTCDATE()) AS TenureDays
FROM dbo.Customer
ORDER BY CustomerID;
GO
Eine Abfrage inlinefähig machen
Die Anforderungen an die Query-Shape in diesem Abschnitt gelten, wenn mindestens ein UDF in einer Abfrage auf skalares UDF-Inlining basiert. Wenn jeder UDF in einer Abfrage durch ExprBlock-Inlining verarbeitet wird, funktionieren diese Abfrageformen ohne die hier gezeigten Neuschreibungen.
Die folgenden Beispiele verwenden die inlineable Datenzugriffsversion von dbo.GetDiscount aus dem vorherigen Abschnitt.
Ersetzen Sie einen allgemeinen Tabellenausdruck
Eine Abfrage, die einen Common Table Expression (CTE) verwendet, kann keine Funktion inlinen, die von skalarem UDF-Inlining abhängt. Die folgende Abfrage wird nicht unterstützt:
WITH CustomerDiscounts AS
(
SELECT
CustomerID,
CustomerName,
dbo.GetDiscount(CustomerID) AS DiscountRate
FROM dbo.Customer
)
SELECT CustomerID, CustomerName, DiscountRate
FROM CustomerDiscounts;
GO
Materialisiere das Ergebnis in einer temporären Tabelle und frage dann die temporäre Tabelle ab:
DROP TABLE IF EXISTS #CustomerDiscounts;
GO
CREATE TABLE #CustomerDiscounts
(
CustomerID INT NOT NULL,
CustomerName VARCHAR(100) NOT NULL,
DiscountRate DECIMAL(5, 2) NOT NULL
)
WITH (DISTRIBUTION = ROUND_ROBIN);
GO
INSERT INTO #CustomerDiscounts
(
CustomerID,
CustomerName,
DiscountRate
)
SELECT
CustomerID,
CustomerName,
dbo.GetDiscount(CustomerID)
FROM dbo.Customer;
GO
SELECT CustomerID, CustomerName, DiscountRate
FROM #CustomerDiscounts;
GO
Verschieben Sie einen UDF-Call aus GROUP BY
Die folgende Abfrage ruft die UDF direkt in der GROUP BY Klausel auf und wird für eine Funktion, die auf skalarer UDF-Inlining basiert, nicht unterstützt:
SELECT
dbo.GetDiscount(CustomerID) AS DiscountRate,
COUNT(*) AS CustomerCount
FROM dbo.Customer
GROUP BY dbo.GetDiscount(CustomerID);
GO
Berechnen Sie das UDF-Ergebnis in einer abgeleiteten Tabelle und gruppieren Sie das Ergebnis dann in der äußeren Abfrage:
SELECT
DiscountRate,
COUNT(*) AS CustomerCount
FROM
(
SELECT dbo.GetDiscount(CustomerID) AS DiscountRate
FROM dbo.Customer
) AS CustomerDiscounts
GROUP BY DiscountRate;
GO
Verwenden Sie ein Spaltenalias in ORDER BY
Vermeiden Sie es, eine UDF, die von skalarem UDF-Inlining abhängt, direkt in der ORDER BY-Klausel aufzurufen. Das Ergebnis nur einmal auswählen und nach dem Spaltenalias oder der Spaltennummer sortieren:
SELECT
CustomerID,
CustomerName,
dbo.GetDiscount(CustomerID) AS DiscountRate
FROM dbo.Customer
ORDER BY DiscountRate;
GO
Erstellen Sie ein nicht-inlineables skalares UDF
Möglicherweise benötigen Sie eine Funktion für eine eigenständige Berechnung, selbst wenn ihre Definition nicht inline eingefügt werden kann. Zum Beispiel könnte eine Anwendung oder ein Bericht einmal ein UDF aufrufen, um eine Geschäftskennzahl zu berechnen.
Die folgende Funktion liest den Jahresumsatz aus der Kundentabelle aus und verwendet dann eine Schleife WHILE , um den durchschnittlichen monatlichen Umsatz für jeden verbleibenden Monat hinzuzufügen. Da die Funktion auf Tabellendaten zugreift, verlässt sie sich auf skalares UDF-Inlining, das keine Unterstützung WHILEbietet. Die Funktionsdefinition ist daher nicht inlineierbar.
Verwenden Sie WITH INLINE = AUTO, damit die Funktion erstellt werden kann, auch wenn ihre Definition nicht inline-fähig ist:
CREATE OR ALTER FUNCTION dbo.GetProjectedAnnualRevenue (@MonthsElapsed INT)
RETURNS DECIMAL(18, 2)
WITH INLINE = AUTO
AS
BEGIN
DECLARE @YearToDateRevenue DECIMAL(38, 6);
DECLARE @ProjectedRevenue DECIMAL(38, 6);
DECLARE @MonthNumber INT = @MonthsElapsed + 1;
IF @MonthsElapsed BETWEEN 1 AND 12
BEGIN
SELECT @YearToDateRevenue = SUM(YearToDateRevenue)
FROM dbo.Customer;
SET @ProjectedRevenue = @YearToDateRevenue;
WHILE @MonthNumber <= 12
BEGIN
SET @ProjectedRevenue =
@ProjectedRevenue + (@YearToDateRevenue / @MonthsElapsed);
SET @MonthNumber = @MonthNumber + 1;
END;
END;
RETURN @ProjectedRevenue;
END;
GO
Verwenden Sie einen eigenständigen Aufruf, um die Kennzahl einmal für das Dashboard zu berechnen:
DECLARE @ProjectedAnnualRevenue DECIMAL(18, 2);
SET @ProjectedAnnualRevenue =
dbo.GetProjectedAnnualRevenue(MONTH(GETUTCDATE()));
SELECT @ProjectedAnnualRevenue AS ProjectedAnnualRevenue;
GO
Die Abfrage liefert prognostizierte Jahresumsätze basierend auf dem durchschnittlichen monatlichen Umsatz bis zum aktuellen UTC-Monat.
INLINE = AUTO erlaubt die Erstellung der Funktion, macht aber keine nicht-inlineable Funktion für die Verwendung in einer verteilten Abfrage geeignet. Zum Beispiel kann nicht dbo.GetProjectedAnnualRevenue in einer SELECT ... FROM dbo.Customer Abfrage verwendet werden.