Freigeben über


Inlining benutzerdefinierter Skalarfunktionen

Gilt für: SQL Server 2019 (15.x) Azure SQL-DatenbankAzure SQL Managed InstanceSQL Analytics-Endpunkt in Microsoft Fabric Lager in Microsoft FabricSQL-Datenbank in Microsoft Fabric

Dieser Artikel stellt eine Einführung in das Inlining benutzerdefinierter Skalarfunktionen dar. Dabei handelt es sich um ein Feature für die intelligente Abfrageverarbeitung in SQL-Datenbanken. Diese Funktion verbessert die Leistung von Abfragen, die skalare UDFs in SQL Server 2019 (15.x) und neueren Versionen aufrufen.

Benutzerdefinierte T-SQL-Skalarfunktionen

Benutzerdefinierte Funktionen (User-defined functions, UDF), die in Transact-SQL implementiert werden und einen einzelnen Datenwert zurückgeben, werden als benutzerdefinierte Transact-SQL-Skalarfunktionen bezeichnet. Benutzerdefinierte Transact-SQL-Funktionen sind gut geeignet, um Code in Transact-SQL-Abfragen wiederzuverwenden und Modularität zu erreichen. Einige Berechnungen (z.B. komplexe Geschäftsregeln) können einfacher in imperativer UDF-Form ausgedrückt werden. Mit benutzerdefinierten Funktionen können Sie eine komplexe Logik erstellen, ohne komplexe SQL-Abfragen schreiben zu können. Weitere Informationen zu benutzerdefinierten Funktionen (UDFs) finden Sie unter Erstellen von benutzerdefinierten Funktionen (Datenbank-Engine).

Leistung von benutzerdefinierten Skalarfunktionen

Die Leistung von benutzerdefinierten Skalarfunktionen ist aus folgenden Gründen häufig niedrig:

  • Iterativer Aufruf. Benutzerdefinierte Funktionen werden einmal pro qualifiziertem Tupel iterativ aufgerufen. Durch diese Funktionsaufrufe entstehen zusätzliche Kosten für den Kontextwechsel. Dies betrifft besonders benutzerdefinierte Funktionen, die Transact-SQL-Abfragen in ihrer Definition ausführen.

  • Keine Kostenberechnung. Während der Optimierung fallen nur Kosten für relationale Operatoren an, nicht für Skalaroperatoren. Vor der Einführung benutzerdefinierter Skalarfunktionen waren andere Skalaroperatoren in der Regel günstig, sodass keine Kostenberechnung nötig war. Es war ausreichend, geringe CPU-Kosten für einen Skalarvorgang hinzuzufügen. In einigen Szenarios sind die tatsächlichen Kosten jedoch wichtig und werden dennoch nicht ausreichend repräsentiert.

  • Interpretierte Ausführung. Benutzerdefinierte Funktionen werden als Anweisungsbatch ausgewertet und Anweisung für Anweisung ausgeführt. Jede Anweisung wird kompiliert, und der kompilierte Plan wird zwischengespeichert. Die Zwischenspeicherung spart zwar Zeit, da Neukompilierungen vermieden werden, aber jede Anweisung wird isoliert ausgeführt. Es können keine anweisungsübergreifenden Optimierungen durchgeführt werden.

  • Serielle Ausführung. SQL Server lässt in Abfragen, die benutzerdefinierte Funktionen aufrufen, keinen abfrageinternen Parallelismus zu.

Automatisches Inlining von benutzerdefinierrten Skalarfunktionen

Mit dem Feature für das Inlining benutzerdefinierter Skalarfunktionen soll die Leistung von Abfragen verbessert werden, die benutzerdefinierte T-SQL-Skalarfunktionen ausführen, bei denen die Ausführung der benutzerdefinierten Funktion den entscheidenden Engpass darstellt.

Mit diesem neuen Feature werden benutzerdefinierte Skalarfunktionen automatisch in Skalarausdrücke oder skalare Unterabfragen transformiert, die in der aufrufenden Abfrage den UDF-Operator ersetzen. Diese Ausdrücke und Unterabfragen werden anschließend optimiert. Infolgedessen verfügt der Abfrageplan nicht mehr über einen benutzerdefinierten Funktionsoperator, sondern seine Auswirkungen werden im Plan beobachtet, wie bei Views oder inline table-valued functions (TVFs).

Automatische Inlineierung von skalaren UDFs in Microsoft Fabric Data Warehouse

In Microsoft Fabric Data-Warehouse werden skalare UDFs (aktuell in der Vorschau) bei der Kompilierung automatisch inline angelegt, wenn der Body der Funktion und die aufrufende Abfrage die Anforderungen für das Inlining erfüllen. Weitere Informationen finden Sie unter CREATE FUNCTION und Scalar UDF inlining.

Beispiele

Die Beispiele in diesem Abschnitt verwenden die TPC-H Benchmark-Datenbank. Weitere Informationen finden Sie unter der TPC-H Homepage.

A. Skalare UDF mit einer einzigen Anweisung

Sehen Sie sich die folgende Abfrage an:

SELECT L_SHIPDATE,
       O_SHIPPRIORITY,
       SUM(L_EXTENDEDPRICE * (1 - L_DISCOUNT))
FROM LINEITEM
     INNER JOIN ORDERS
         ON O_ORDERKEY = L_ORDERKEY
GROUP BY L_SHIPDATE, O_SHIPPRIORITY
ORDER BY L_SHIPDATE;

Diese Abfrage berechnet die Summe der reduzierten Preise für Einzelposten und gruppiert die Ergebnisse nach Versanddatum und Versandpriorität. Der Ausdruck L_EXTENDEDPRICE *(1 - L_DISCOUNT) enthält die Formel für den reduzierten Preis eines bestimmten Einzelpostens. Solche Formeln können in Funktionen extrahiert werden, um Modularität und Wiederverwendbarkeit zu erreichen.

CREATE FUNCTION dbo.discount_price
(
    @price DECIMAL (12, 2),
    @discount DECIMAL (12, 2)
)
RETURNS DECIMAL (12, 2)
AS
BEGIN
    RETURN @price * (1 - @discount);
END

Die Abfrage kann nun geändert werden, um diese benutzerdefinierte Funktion aufzurufen.

SELECT L_SHIPDATE,
       O_SHIPPRIORITY,
       SUM(dbo.discount_price(L_EXTENDEDPRICE, L_DISCOUNT))
FROM LINEITEM
     INNER JOIN ORDERS
         ON O_ORDERKEY = L_ORDERKEY
GROUP BY L_SHIPDATE, O_SHIPPRIORITY
ORDER BY L_SHIPDATE;

Die Abfrage mit der UDF schneidet aus den oben genannten Gründen schlecht ab. Durch das Inlining der benutzerdefinierten Skalarfunktion wird der Skalarausdruck im Textkörper der benutzerdefinierten Funktion direkt in der Abfrage ersetzt. Die Ergebnisse dieser Abfrage werden in folgender Tabelle aufgeführt:

Abfrage: Abfrage ohne benutzerdefinierte Funktion Abfrage mit benutzerdefinierter Funktion (ohne Inlining) Abfrage mit Inlining benutzerdefinierter Skalarfunktionen
Execution time: 1.6 Sekunden 29 Minute 11 Sekunden 1.6 Sekunden

Diese Zahlen basieren auf einer CCI-Datenbank mit 10 GB (mit dem TPC-H-Schema), die auf einem Computer mit Dualprozessor (12 Kerne), 96 GB RAM und SSD-Sicherung ausgeführt wird. Dabei wurden die Kompilier- und die Ausführungszeit mit einem kalten Prozedurcache und Pufferpool eingeschlossen. Die Standardkonfiguration wurde verwendet, und es wurden keine weiteren Indizes erstellt.

B. Skalare UDF mit mehreren Anweisungen

Für benutzerdefinierte Skalarfunktionen, die über mehrere T-SQL-Anweisungen implementiert werden, z.B. Variablenzuweisungen und bedingte Verzweigungen, kann ebenfalls ein Inlining durchgeführt werden. Sehen Sie sich folgende benutzerdefinierte Skalarfunktion an, die die Servicekategorie für einen bestimmten Kunden bestimmt, wenn ein benutzerdefinierter Schlüssel vorhanden ist. Die Kategorie wird erreicht, indem zuerst der Gesamtpreis aller Bestellungen des Kunden mithilfe einer SQL-Abfrage berechnet wird. Anschließend wird eine IF (...) ELSE-Logik verwendet, um die Kategorie auf Grundlage des Gesamtpreises zu bestimmen.

CREATE OR ALTER FUNCTION dbo.customer_category (@ckey INT)
RETURNS CHAR (10)
AS
BEGIN
    DECLARE @total_price AS DECIMAL (18, 2);
    DECLARE @category AS CHAR (10);
    SELECT @total_price = SUM(O_TOTALPRICE)
    FROM ORDERS
    WHERE O_CUSTKEY = @ckey;
    IF @total_price < 500000
        SET @category = 'REGULAR';
    ELSE
        IF @total_price < 1000000
            SET @category = 'GOLD';
        ELSE
            SET @category = 'PLATINUM';
    RETURN @category;
END

Sehen Sie sich nun eine Abfrage an, die diese benutzerdefinierte Funktion aufruft.

SELECT C_NAME,
       dbo.customer_category(C_CUSTKEY)
FROM CUSTOMER;

Der Ausführungsplan für diese Abfrage in SQL Server 2017 (14.x) (Kompatibilitätsgrad 140 und früher) sieht folgendermaßen aus:

Screenshot des Abfrageplans ohne Inlining.

Der Plan zeigt, dass SQL Server in diesem Fall eine einfache Strategie übernimmt: Für jedes Tupel in der CUSTOMER-Tabelle werden die benutzerdefinierte Funktion aufgerufen und die Ergebnisse ausgegeben. Diese Strategie ist jedoch zu einfach und nicht effizient. Durch Inlining werden solche benutzerdefinierten Funktionen in gleichwertige skalare Unterabfragen transformiert, die die benutzerdefinierte Funktion in der aufrufenden Abfrage ersetzen.

Für dieselbe Abfrage sieht der Plan mit der inlinefähigen UDF wie folgt aus.

Screenshot des Abfrageplans mit Inlining.

Wie zuvor erwähnt enthält der Abfrageplan keinen UDF-Operator mehr. Seine Auswirkungen sind nun im Plan ersichtlich, z.B. Ansichten oder Inline-Tabellenwertfunktionen. Hier sind die wichtigsten Beobachtungen, die aus dem vorherigen Plan resultieren:

  • SQL Server leitet die implizite Verknüpfung zwischen CUSTOMER und ORDERS ab und macht sie über einen Verknüpfungsoperator explizit.

  • SQL Server leitet auch das implizite GROUP BY O_CUSTKEY on ORDERS ab und verwendet IndexSpool + StreamAggregate für die Implementierung.

  • SQL Server verwendet nun einen Parallelismus für alle Operatoren.

Je nach Komplexität der Logik in der benutzerdefinierten Funktion kann der resultierende Abfrageplan größer und komplexer werden. Wie wir sehen können, sind die Operationen innerhalb der UDF jetzt nicht mehr intransparent, sodass der Abfrageoptimierer in der Lage ist, diese Operationen zu berechnen und zu optimieren. Da die benutzerdefinierte Funktion sich nicht mehr im Plan befindet, wird der iterative Aufruf derselben durch einen Plan ersetzt, der den Aufwand, der durch Funktionsaufrufe entsteht, vollständig vermeidet.

Inlinefähige skalare UDF-Anforderungen

Eine skalare T-SQL UDF kann inlinefähig sein, wenn die Funktionsdefinition zulässige Konstrukte verwendet und die Funktion in einem Kontext verwendet wird, der Inlining ermöglicht:

Alle der folgenden Bedingungen der UDF-Definition müssen erfüllt sein:

  • Die benutzerdefinierte Funktion wurde mit folgenden Konstrukten geschrieben:
    • DECLARE, SET: Variablendeklaration und -zuweisungen
    • SELECT: SQL-Abfrage mit einer bzw. mehreren Variablenzuweisungen 1
    • IF / ELSE: Verzweigung mit beliebigen Schachtelungsebenen
    • RETURN: eine oder mehrere RETURN-Anweisungen Ab SQL Server 2019 (15.x) CU5 darf die UDF nur eine einzige RETURN-Anweisung enthalten, um für das Inlining in Frage zu kommen 6.
    • UDF : Geschachtelte bzw. rekursive Funktionsaufrufe 2.
    • Sonstige: relationale Operatoren wie EXISTS, IS NULL
  • Die benutzerdefinierte Funktion ruft keine intrinsische Funktion auf, die zeitabhängig ist (wie GETDATE()) oder Nebeneffekte3 hat (wie NEWSEQUENTIALID()).
  • Die benutzerdefinierte Funktion verwendet die EXECUTE AS CALLER-Klausel (Standardverhalten, wenn die EXECUTE AS-Klausel nicht angegeben wurde).
  • Die benutzerdefinierte Funktion verweist nicht auf Tabellenvariablen oder Tabellenwertparameter.
  • Die benutzerdefinierte Funktion wird nicht nativ kompiliert (Interop wird unterstützt).
  • Die benutzerdefinierte Funktion verweist nicht auf benutzerdefinierte Typen.
  • Der UDF werden keine Signaturen hinzugefügt 9.
  • Bei der benutzerdefinierten Funktion handelt es sich nicht um eine Partitionsfunktion.
  • Die benutzerdefinierte Funktion enthält keine Verweise auf allgemeine Tabellenausdrücke (Common Table Expressions, CTEs).
  • Die benutzerdefinierte Funktion enthält keine Verweise auf intrinsische Funktionen, die die Ergebnisse ändern können, wenn ein Inlinevorgang ausgeführt wird (z. B. @@ROWCOUNT) 4.
  • Die benutzerdefinierte Funktion enthält keine Aggregatfunktionen, die als Parameter an eine Skalar-UDF übergeben werden 4.
  • Die benutzerdefinierte Funktion verweist nicht auf integrierte Sichten (z. B. OBJECT_ID) 4.
  • Die UDF verweist nicht auf XML-Methoden 5.
  • Die benutzerdefinierte Funktion enthält keine SELECT-Abfrage mit ORDER BY ohne TOP 1-Klausel 5.
  • Die benutzerdefinierte Funktion enthält keine SELECT-Abfrage, die eine Zuweisung mit der ORDER BY-Klausel durchführt (z. B. SELECT @x = @x + 1 FROM table1 ORDER BY col1) 5.
  • Die UDF enthält nicht mehrere RETURN-Anweisungen 6.
  • Die UDF verweist nicht auf die STRING_AGG-Funktion 6.
  • Die benutzerdefinierte Funktion verweist nicht auf Remotetabellen 7.
  • Die benutzerdefinierte Funktion verweist nicht auf verschlüsselte Spalten 8.
  • Die benutzerdefinierte Funktion enthält keine Verweise auf WITH XMLNAMESPACES8.
  • Wenn die Definition der benutzerdefinierten Funktion beispielsweise zu Tausenden Codezeilen führt, führt SQL Server für diese möglicherweise kein Inlining durch.

1SELECT Mit einer Variablenakkumulation/-aggregation (z. B. SELECT @val += col1 FROM table1) wird kein Inlining unterstützt.

2 Für rekursive benutzerdefinierte Funktionen wird das Inlining nur bis zu einem bestimmten Grad durchgeführt.

3 Intrinsische Funktionen, deren Ergebnisse von der aktuellen Systemzeit abhängen, sind zeitabhängig. Eine intrinsische Funktion, die möglicherweise einen internen globalen Status aktualisiert, ist ein Beispiel für eine Funktion mit Nebeneffekten. Solche Funktionen geben bei jedem Aufruf unterschiedliche Ergebnisse zurück, die auf dem internen Status basieren.

4 Einschränkung hinzugefügt in SQL Server 2019 (15.x) CU 2

5 Einschränkung hinzugefügt in SQL Server 2019 (15.x) CU 4

6 Einschränkung hinzugefügt in SQL Server 2019 (15.x) CU 5

7 Einschränkung hinzugefügt in SQL Server 2019 (15.x) CU 6

8 Einschränkung hinzugefügt in SQL Server 2019 (15.x) CU 11

9 Signaturen können nach dem Erstellen einer benutzerdefinierte Funktion hinzugefügt und gelöscht werden können. Deshalb wird bei der Kompilierung der Abfrage, die auf eine benutzerdefinierte Skalarfunktion verweist, entschieden, ob für diese ein Inlining durchgeführt werden soll oder nicht. Systemfunktionen sind z. B. in der Regel mit einem Zertifikat signiert. Sie können sys.crypt_properties verwenden, um zu ermitteln, welche Objekte signiert sind.

Alle der folgenden Bedingungen des Ausführungskontextes müssen erfüllt sein:

  • Die benutzerdefinierte Funktion wird in der ORDER BY-Klausel nicht verwendet.
  • Die Abfrage, die eine benutzerdefinierte Skalarfunktion aufruft, verweist in der GROUP BY-Klausel nicht auf einen Aufruf einer benutzerdefinierten Skalarfunktion.
  • Die Abfrage, die eine benutzerdefinierte Skalarfunktion in der Auswahlliste mit der DISTINCT-Klausel aufruft, verfügt nicht über eine ORDER BY-Klausel.
  • Die benutzerdefinierte Funktion wird nicht aus einer RETURN-Anweisung aufgerufen 1.
  • Die Abfrage, die die benutzerdefinierte Funktion aufruft, enthält keine allgemeinen Tabellenausdrücke (Common Table Expressions, CTEs) 3.
  • Die Abfrage, die die benutzerdefinierte Funktion aufruft, verwendetGROUPING SETS, CUBEoderROLLUPnicht2.
  • Die Abfrage, die die benutzerdefinierte Funktion aufruft, enthält keine Variable, die als Zuweisungsparameter für die benutzerdefinierte Funktion verwendet wird (z. B. SELECT @y = 2, @x = UDF(@y)) 2.
  • Die benutzerdefinierte Funktion wird nicht in einer berechneten Spalte oder in der Definition einer CHECK-Einschränkung verwendet.

1 Einschränkung hinzugefügt in SQL Server 2019 (15.x) CU 5

2 Einschränkung hinzugefügt in SQL Server 2019 (15.x) CU 6

3 Einschränkung hinzugefügt in SQL Server 2019 (15.x) CU 11

Informationen zu den neuesten T-SQL Inlining-Fixes für skalare UDFs und zu den Änderungen an den Inlining-Zulässigkeitsszenarien finden Sie im Knowledge Base Artikel: FIX: Skalare UDF-Inlining-Probleme in SQL Server 2019.

Überprüfen, ob eine UDF inlinefähig ist

Für jede benutzerdefinierte T-SQL-Skalarfunktion enthält die Katalogansicht sys.sql_modules eine Eigenschaft namens is_inlineable, die angibt, ob für eine benutzerdefinierte Funktion ein Inlining möglich ist.

Die is_inlineable-Eigenschaft wird von den Konstrukten abgeleitet, die in der Definition der benutzerdefinierten Skalarfunktion gefunden werden. Es wird nicht überprüft, ob für die benutzerdefinierte Funktion zum Zeitpunkt der Kompilierung tatsächlich ein Inlining möglich ist. Weitere Informationen finden Sie im Abschnitt zu den Bedingungen für Inlining.

Ein Wert von 1 zeigt an, dass die UDF inlinefähig ist, und 0 zeigt das Gegenteil an. Diese Eigenschaft hat auch für alle inlinefähigen TVFs den Wert 1. Für alle anderen Module ist der Wert 0.

Wenn eine skalare UDF inlinefähig ist, bedeutet dies nicht, dass sie immer inlinefähig ist. SQL Server entscheidet (pro Abfrage, pro UDF), ob eine UDF inlinefähig ist. Sehen Sie sich die Liste der Anforderungen weiter oben in diesem Artikel an.

SELECT b.name,
       b.type_desc,
       a.is_inlineable
FROM sys.sql_modules AS a
     INNER JOIN sys.objects AS b
         ON a.object_id = b.object_id
WHERE b.type IN ('IF', 'TF', 'FN');

Überprüfen, ob Inlining stattgefunden hat

Wenn alle Bedingungen erfüllt sind und SQL Server ein Inlining durchführt, wird die benutzerdefinierte Funktion in einen relationalen Ausdruck transformiert. Anhand des Abfrageplans können Sie herausfinden, ob Inlining stattgefunden hat:

  • Das Plan-XML enthält keinen <UserDefinedFunction> XML-Knoten für eine UDF, die erfolgreich eingebettet wurde.
  • Bestimmte erweiterte Ereignisse werden ausgegeben.

Aktivieren des Inlinings von skalaren UDFs

Sie können Workloads automatisch für das Inlining benutzerdefinierter Skalarfunktionen zulassen, indem Sie den Kompatibilitätsgrad 150 für die Datenbank aktivieren. Diesen können Sie mit Transact-SQL festlegen. Zum Beispiel:

ALTER DATABASE [WideWorldImportersDW]
    SET COMPATIBILITY_LEVEL = 150;

Abgesehen von diesem Schritt müssen keine weiteren Änderungen an UDFs oder Abfragen vorgenommen werden, um diese Funktion zu nutzen.

Deaktivieren des Inlinings von benutzerdefinierten Skalarfunktionen ohne Änderung des Kompatibilitätsgrads

Das Inlining von benutzerdefinierten Skalarfunktionen kann im Datenbank- oder Anweisungs-, oder UDF-Bereich deaktiviert werden, während der Datenbankkompatibilitätsgrad weiterhin bei 150 und höher bleibt. Führen Sie folgende Anweisung im Kontext einer Datenbank aus, um das Inlining für benutzerdefinierte Skalarfunktionen im Datenbankbereich zu deaktivieren:

ALTER DATABASE SCOPED CONFIGURATION SET TSQL_SCALAR_UDF_INLINING = OFF;

Führen Sie folgende Anweisung im Kontext einer Datenbank aus, um das Inlining für benutzerdefinierte Skalarfunktionen für eine Datenbank wieder zu aktivieren:

ALTER DATABASE SCOPED CONFIGURATION SET TSQL_SCALAR_UDF_INLINING = ON;

Wenn ON, erscheint diese Einstellung als aktiviert in sys.database_scoped_configurations.

Sie können das Inlining benutzerdefinierter Skalarfunktionen für eine bestimmte Abfrage auch deaktivieren, indem Sie DISABLE_TSQL_SCALAR_UDF_INLINING als USE HINT-Abfragehinweis festlegen.

Ein USE HINT-Abfragehinweis hat Vorrang vor einer datenbankweit gültigen Konfiguration oder einer Einstellung des Kompatibilitätsgrads.

Zum Beispiel:

SELECT L_SHIPDATE,
       O_SHIPPRIORITY,
       SUM(dbo.discount_price(L_EXTENDEDPRICE, L_DISCOUNT))
FROM LINEITEM
     INNER JOIN ORDERS
         ON O_ORDERKEY = L_ORDERKEY
GROUP BY L_SHIPDATE, O_SHIPPRIORITY
ORDER BY L_SHIPDATE
OPTION (USE HINT('DISABLE_TSQL_SCALAR_UDF_INLINING'));

Das Inlining benutzerdefinierter Skalarfunktionen kann auch für eine bestimmte benutzerdefinierte Funktion deaktiviert werden, indem Sie die INLINE-Klausel in der CREATE FUNCTION- oder ALTER FUNCTION-Anweisung verwenden. Zum Beispiel:

CREATE OR ALTER FUNCTION dbo.discount_price
(
    @price DECIMAL (12, 2),
    @discount DECIMAL (12, 2)
)
RETURNS DECIMAL (12, 2)
WITH INLINE = OFF
AS
BEGIN
    RETURN @price * (1 - @discount);
END

Sobald die oben genannte Anweisung ausgeführt wurde, wird für diese benutzerdefinierte Funktion kein Inlining durchgeführt, wenn sie von einer Abfrage aufgerufen wird. Führen Sie folgende Anweisung aus, um das Inlining für diese benutzerdefinierte Funktion wieder zu aktivieren:

CREATE OR ALTER FUNCTION dbo.discount_price
(
    @price DECIMAL (12, 2),
    @discount DECIMAL (12, 2)
)
RETURNS DECIMAL (12, 2)
WITH INLINE = ON
AS
BEGIN
    RETURN @price * (1 - @discount);
END

Die INLINE-Klausel ist nicht verbindlich. Wenn die INLINE-Klausel nicht festgelegt ist, wird sie automatisch auf ON/OFF festgelegt, je nachdem, ob ein Inlining für die benutzerdefinierte Funktion durchgeführt werden kann. Wenn INLINE = ON festgelegt ist, aber für die benutzerdefinierte Funktion kein Inlining durchgeführt werden kann, wird ein Fehler ausgegeben.

Hinweise

Wie in diesem Artikel beschrieben wurde, wird beim Inlining einer benutzerdefinierten Skalarfunktion eine Abfrage mit benutzerdefinierten Skalarfunktionen in eine Abfrage mit einer gleichwertigen skalaren Unterabfrage transformiert. Aufgrund dieser Transformation werden Sie in den folgenden Szenarien möglicherweise einige Unterschiede im Verhalten feststellen:

  • Das Inlining führt zu einem anderen Abfragehash für den gleichen Abfragetext.

  • Bestimmte Warnungen in Anweisungen innerhalb der UDF (wie z. B. Dividieren durch Null usw.), die zuvor möglicherweise verborgen waren, können aufgrund des Inlinings auftauchen.

  • Joinhinweise auf Abfrageebene sind möglicherweise nicht mehr gültig, da durch das Inlining neue Joins hinzugefügt werden. Stattdessen müssen lokale Join-Hinweise verwendet werden.

  • Ansichten, die auf benutzerdefinierte Inlineskalarfunktionen verweisen, können nicht indiziert werden. Wenn Sie einen Index in einer entsprechenden Ansicht erstellen müssen, sollten Sie das Inlining für die benutzerdefinierten Funktionen deaktivieren, auf die verwiesen wird.

  • Durch das Inlining benutzerdefinierter Funktionen kann das Verhalten der dynamischen Datenmaskierung sich ändern.

    In bestimmten Situationen (abhängig von der Logik in der UDF) kann das Inlining in Bezug auf die Maskierung von Ausgabespalten konservativer sein. In Szenarios, bei denen es sich bei den Spalten, auf die in einer benutzerdefinierten Funktion verwiesen wird, nicht um Ausgabespalten handelt, werden diese nicht maskiert.

  • Wenn eine benutzerdefinierte Funktion auf integrierte Funktionen wie SCOPE_IDENTITY(), @@ROWCOUNT oder @@ERROR verweist, ändert sich der Wert, der von der integrierten Funktion zurückgegeben wird, durch das Inlining. Diese Änderung im Verhalten geht darauf zurück, dass das Inlining den Bereich der Anweisungen in der benutzerdefinierten Funktion ändert. Ab SQL Server 2019 (15.x) CU2 wird das Inlining blockiert, wenn die UDF bestimmte intrinsische Funktionen referenziert (zum Beispiel @@ROWCOUNT).

  • Wenn eine Variable mit dem Ergebnis einer inlinisierten UDF zugewiesen wird und sie auch als index_column_name in FORCESEEKAbfragehinweise (Transact-SQL) verwendet wird, führt dies zu Fehler 8622, was darauf hinweist, dass der Abfrageprozessor aufgrund der in der Abfrage definierten Hinweise keinen Abfrageplan erstellen konnte.