Et rien sur les fonctions. Pourquoi les informations de fonction sont-elles manquantes dans le plan réel?
C'est par conception, pour des raisons de performances.
Les fonctions qui contiennent BEGIN
et END
dans la définition créent un nouveau cadre de pile T-SQL pour chaque ligne d'entrée. Autrement dit, le corps de la fonction est exécuté séparément pour chaque ligne d'entrée . Ce fait unique explique la plupart des problèmes de performances associés aux fonctions scalaires et multi-instructions T-SQL (notez que les fonctions de valeur de table en ligne n'utilisent pas la BEGIN...END
syntaxe).
Dans le contexte de votre question, cela donnerait une SHOWPLAN
sortie complète pour chaque ligne. La sortie du plan XML est assez verbeuse et coûteuse à produire, donc produire une sortie complète pour chaque ligne serait une mauvaise idée en termes généraux.
Exemple
Considérez la fonction scalaire T-SQL ci-dessous, créée dans la base de données exemple AdventureWorks , qui renvoie le nom d'un produit en fonction de son ID:
CREATE FUNCTION dbo.DumbNameLookup
(
@ProductID integer
)
RETURNS dbo.Name
AS
BEGIN
RETURN
(
SELECT
p.Name
FROM Production.Product AS p
WHERE
p.ProductID = @ProductID
);
END;
Plan de pré-exécution
Un plan de pré-exécution (plan estimé dans SSMS) affiche des informations de plan pour l'instruction parent et les appels de fonction imbriqués:
-- Pre-execution plan shows main query and nested function call
SET SHOWPLAN_XML ON;
GO
SELECT dbo.DumbNameLookup(1);
GO
SET SHOWPLAN_XML OFF;
Sortie SSMS:
Le même XML affiché dans SQL Sentry Plan Explorer montre plus clairement la nature imbriquée des appels:
Sortie post-exécution
SSMS affiche les détails de la requête principale uniquement lorsque la sortie du plan de post-exécution est demandée:
-- Post-execution plan shows main query only
SET STATISTICS XML ON;
SELECT dbo.DumbNameLookup(1);
SET STATISTICS XML OFF;
L'impact sur les performances d'une action différente peut être illustré à l'aide de la classe d'événements Showplan XML Statistics Profile dans SQL Server Profiler, à l'aide d'une requête qui appelle la fonction plusieurs fois (une fois par ligne d'entrée):
SELECT TOP (5)
p.ProductID,
dbo.DumbNameLookup(p.ProductID)
FROM Production.Product AS p;
Sortie du profileur:
Il existe cinq plans de post-exécution distincts pour les exécutions de fonction et un pour la requête parent. Les cinq plans de fonction ressemblent à ceci dans le volet inférieur du profileur:
Le plan de requête parent est le suivant:
L'exécution de la requête sans la TOP (5)
clause entraîne un plan d'exécution complet pour chacune des 504 lignes de la table Product. Vous pouvez probablement voir comment cela deviendrait rapidement incontrôlable avec des tables plus grandes.
La situation des déclencheurs est inversée. Ceux-ci ne présentent aucune information sur le plan de pré-exécution, mais incluent un plan de post-exécution. Cela reflète la nature basée sur l'ensemble des déclencheurs; chacun est tiré une fois pour toutes les lignes affectées, plutôt qu'une fois par ligne.