Plan de requête estimé ou réel avec appels de fonction

11

J'ai cette requête sur SQL Server, une requête de réplication de fusion:

SELECT DISTINCT
    b.tablenick,
    b.rowguid,
    c.generation,
    sys.fn_MSgeneration_downloadonly
    (
        c.generation,
        c.tablenick
    )
FROM #belong b
LEFT OUTER JOIN dbo.MSmerge_contents c ON 
    c.tablenick = b.tablenick
    AND c.rowguid = b.rowguid;

Le plan de requête estimé inclut des informations sur 3 requêtes:

  1. La requête ci-dessus
  2. L'appel de fonction à fn_MSgeneration_downloadonly
  3. L'appel de fonction à fn_MSArticle_has_downloadonly_property

Le plan de requête réel comprend uniquement ces informations:

  1. La requête ci-dessus

Rien sur les fonctions. Pourquoi les informations de fonction sont-elles manquantes dans le plan réel?

J'ai essayé ces options:

SET STATISTICS PROFILE ON
SET STATISTICS XML ON

Ce qui a créé un plan réel, mais il manquait les parties 2 et 3, comme lorsque j'ai utilisé l'option de plan de requête réelle dans Management Studio.

Si, par exemple, je devais utiliser Profiler pour capturer les informations sur les appels de fonction, quels événements devrais-je sélectionner?


Je n'ai pas trouvé de réponse spécifiquement liée aux plans de requête, mais j'ai profilé SP: StmtStarting et SP: StmtCompleted et il a montré les appels de fonction.

peter
la source

Réponses:

17

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 BEGINet ENDdans 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...ENDsyntaxe).

Dans le contexte de votre question, cela donnerait une SHOWPLANsortie 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:

Plan de pré-exécution SSMS

Le même XML affiché dans SQL Sentry Plan Explorer montre plus clairement la nature imbriquée des appels:

Plan de pré-exécution PE

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;

Post-exécution SSMS

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:

Sortie de trace

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:

Plans de fonction

Le plan de requête parent est le suivant:

Plan parent

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.

Paul White 9
la source
@PaulWhite existe-t-il une bonne raison pour laquelle les plans de déclenchement ne sont pas affichés lors de la demande du plan d'exécution estimé? Cela semble être une fonctionnalité manquante utile. Je pourrais créer un élément de connexion pour cela.
usr
@usr - Peut-être parce que le plan en cache réel qui est sélectionné peut varier en fonction du nombre réel de lignes comme décrit ici? technet.microsoft.com/en-us/library/…
Martin Smith
@MartinSmith, cela pourrait être une raison. Récemment, un élément de connexion pour les plans d'exécution de vérification et de contraintes fk a été marqué comme terminé, donc j'espérais qu'ils feraient la même chose avec les déclencheurs.
usr
@usr - Celui-ci ici ? 3 mois? Ce doit être un record pour une nouvelle demande de fonctionnalité!
Martin Smith
@MartinSmith oui, celui-là. Il a été "corrigé" il y a 1-2. J'espère vraiment ne pas avoir à interroger le magasin de requêtes. J'avais espéré cliquer sur un bouton dans SSMS. En fait, j'ai été surpris de voir un quelconque changement sur une partie du moteur qui n'a pas été touchée depuis des années. Mais peut-être qu'il n'y en avait pas.
usr