Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Multi-Statement-Tabellenwertfunktion vs. Inline-Tabellenwertfunktion

Bei der Untersuchung von Matts Kommentar habe ich meine ursprüngliche Aussage revidiert. Er hat Recht, es gibt einen Leistungsunterschied zwischen einer Inline-Tabellenwertfunktion (ITVF) und einer Multi-Statement-Tabellenwertfunktion (MSTVF), selbst wenn beide einfach eine SELECT-Anweisung ausführen. SQL Server behandelt eine ITVF in etwa wie eine VIEW , dass es anhand der neuesten Statistiken zu den betreffenden Tischen einen Ausführungsplan berechnet. Ein MSTVF entspricht dem Füllen des gesamten Inhalts Ihrer SELECT-Anweisung in eine Tabellenvariable und dem anschließenden Verbinden mit dieser. Daher kann der Compiler keine Tabellenstatistiken für die Tabellen in der MSTVF verwenden. Wenn also alle Dinge gleich sind (was selten der Fall ist), wird der ITVF besser abschneiden als der MSTVF. In meinen Tests war der Leistungsunterschied in der Ausführungszeit vernachlässigbar, aus statistischer Sicht jedoch auffällig.

In Ihrem Fall sind die beiden Funktionen nicht funktional gleichwertig. Die MSTV-Funktion führt bei jedem Aufruf eine zusätzliche Abfrage durch und filtert vor allem nach der Kunden-ID. In einer großen Abfrage wäre der Optimierer nicht in der Lage, andere Join-Typen zu nutzen, da er die Funktion für jede übergebene Kunden-ID aufrufen müsste. Wenn Sie jedoch Ihre MSTV-Funktion wie folgt neu geschrieben haben:

CREATE FUNCTION MyNS.GetLastShipped()
RETURNS @CustomerOrder TABLE
    (
    SaleOrderID    INT         NOT NULL,
    CustomerID      INT         NOT NULL,
    OrderDate       DATETIME    NOT NULL,
    OrderQty        INT         NOT NULL
    )
AS
BEGIN
    INSERT @CustomerOrder
    SELECT a.SalesOrderID, a.CustomerID, a.OrderDate, b.OrderQty
    FROM Sales.SalesOrderHeader a 
        INNER JOIN Sales.SalesOrderHeader b
            ON a.SalesOrderID = b.SalesOrderID
        INNER JOIN Production.Product c 
            ON b.ProductID = c.ProductID
    WHERE a.OrderDate = (
                        Select Max(SH1.OrderDate)
                        FROM Sales.SalesOrderHeader As SH1
                        WHERE SH1.CustomerID = A.CustomerId
                        )
    RETURN
END
GO

In einer Abfrage könnte der Optimierer diese Funktion einmal aufrufen und einen besseren Ausführungsplan erstellen, aber er wäre immer noch nicht besser als ein gleichwertiges, nicht parametrisiertes ITVS oder ein VIEW .

ITVFs sollten gegenüber MSTVFs bevorzugt werden, wenn dies möglich ist, da die Datentypen, die Nullzulässigkeit und die Sortierung aus den Spalten in der Tabelle, während Sie diese Eigenschaften in einer Tabellenwertfunktion mit mehreren Anweisungen deklarieren, und, was wichtig ist, Sie bessere Ausführungspläne vom ITVF erhalten. Nach meiner Erfahrung habe ich nicht viele Umstände gefunden, in denen ein ITVF eine bessere Option als ein VIEW war, aber die Laufleistung kann variieren.

Danke an Matt.

Zusatz

Da ich dies kürzlich gesehen habe, ist hier eine ausgezeichnete Analyse von Wayne Sheffield, die den Leistungsunterschied zwischen Inline-Tabellenwertfunktionen und Multi-Statement-Funktionen vergleicht.

Sein ursprünglicher Blogbeitrag.

Kopieren Sie auf SQL Server Central