En recherchant le commentaire de Matt, j'ai révisé ma déclaration originale. Il a raison, il y aura une différence de performances entre une fonction de table en ligne (ITVF) et une fonction de table à plusieurs instructions (MSTVF) même si elles exécutent toutes deux simplement une instruction SELECT. SQL Server traitera un ITVF un peu comme un VIEW
en ce qu' il calculera un plan d'exécution en utilisant les dernières statistiques sur les tables en question. Un MSTVF équivaut à insérer tout le contenu de votre instruction SELECT dans une variable de table, puis à la joindre. Ainsi, le compilateur ne peut pas utiliser de statistiques de table sur les tables du MSTVF. Ainsi, toutes choses étant égales par ailleurs (ce qui est rarement le cas), l'ITVF sera plus performant que le MSTVF. Lors de mes tests, la différence de performance dans le temps de réalisation était négligeable, mais d'un point de vue statistique, elle était perceptible.
Dans votre cas, les deux fonctions ne sont pas fonctionnellement équivalentes. La fonction MSTV effectue une requête supplémentaire à chaque fois qu'elle est appelée et, plus important encore, filtre sur l'identifiant client. Dans une requête volumineuse, l'optimiseur ne pourrait pas tirer parti d'autres types de jointures car il devrait appeler la fonction pour chaque ID client transmis. Cependant, si vous avez réécrit votre fonction MSTV comme suit :
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
Dans une requête, l'optimiseur serait capable d'appeler cette fonction une fois et de construire un meilleur plan d'exécution, mais ce ne serait toujours pas mieux qu'un ITVS équivalent non paramétré ou un VIEW
.
Les ITVF doivent être préférés aux MSTVF lorsque cela est possible, car les types de données, la nullabilité et le classement des colonnes de la table alors que vous déclarez ces propriétés dans une fonction à valeur de table à plusieurs instructions et, surtout, vous obtiendrez de meilleurs plans d'exécution de l'ITVF. D'après mon expérience, je n'ai pas trouvé beaucoup de circonstances où un ITVF était une meilleure option qu'un VIEW mais le kilométrage peut varier.
Merci à Matt.
Ajout
Depuis que j'ai vu cela arriver récemment, voici une excellente analyse réalisée par Wayne Sheffield comparant la différence de performances entre les fonctions Inline Table Valued et les fonctions Multi-Statement.
Son article de blog original.
Copier sur SQL Server Central