Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Fonction de valeur de table multi-instructions vs fonction de valeur de table en ligne

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