Bij het onderzoeken van de opmerking van Matt heb ik mijn oorspronkelijke verklaring herzien. Hij heeft gelijk, er zal een verschil in prestatie zijn tussen een inline table valued function (ITVF) en een multi-statement table valued function (MSTVF), zelfs als ze allebei gewoon een SELECT-instructie uitvoeren. SQL Server behandelt een ITVF enigszins als een VIEW
in die zin dat het een uitvoeringsplan berekent op basis van de laatste statistieken over de tabellen in kwestie. Een MSTVF komt overeen met het proppen van de volledige inhoud van uw SELECT-instructie in een tabelvariabele en vervolgens daaraan deelnemen. De compiler kan dus geen tabelstatistieken gebruiken voor de tabellen in de MSTVF. Dus als alle dingen gelijk zijn (wat ze zelden zijn), zal de ITVF beter presteren dan de MSTVF. In mijn tests was het prestatieverschil in voltooiingstijd verwaarloosbaar, maar vanuit statistisch oogpunt was het merkbaar.
In uw geval zijn de twee functies niet functioneel equivalent. De MSTV-functie doet elke keer dat deze wordt aangeroepen een extra query en, belangrijker nog, filtert op de klant-ID. In een grote query zou de optimizer geen voordeel kunnen halen uit andere typen joins, omdat deze de functie voor elke doorgegeven customerId zou moeten aanroepen. Als u uw MSTV-functie echter als volgt herschreef:
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 een query zou de optimizer die functie één keer kunnen aanroepen en een beter uitvoeringsplan kunnen bouwen, maar het zou nog steeds niet beter zijn dan een gelijkwaardige, niet-geparametriseerde ITVS of een VIEW
.
ITVF's zouden waar mogelijk de voorkeur moeten krijgen boven MSTVF's, omdat de datatypes, nullabiliteit en sortering van de kolommen in de tabel, terwijl u die eigenschappen in een multi-statement tabel waardeert, functie en, belangrijker nog, u betere uitvoeringsplannen krijgt van de ITVF. In mijn ervaring heb ik niet veel omstandigheden gevonden waarin een ITVF een betere optie was dan een VIEW, maar de kilometerstand kan variëren.
Met dank aan Matt.
Toevoeging
Aangezien ik dit onlangs zag opduiken, is hier een uitstekende analyse uitgevoerd door Wayne Sheffield, waarin het prestatieverschil tussen Inline Table Valued-functies en Multi-Statement-functies wordt vergeleken.
Zijn originele blogpost.
Kopiëren op SQL Server Central