Plano de consulta estimado versus real com chamadas de função

11

Eu tenho essa consulta no SQL Server, uma consulta de replicação de mesclagem:

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;

O plano de consulta estimado inclui informações sobre três consultas:

  1. A consulta acima
  2. A chamada de função para fn_MSgeneration_downloadonly
  3. A chamada de função para fn_MSArticle_has_downloadonly_property

O plano de consulta real inclui apenas essas informações:

  1. A consulta acima

Nada sobre as funções. Por que as informações de função estão ausentes no plano real?

Eu tentei estas opções:

SET STATISTICS PROFILE ON
SET STATISTICS XML ON

O que criou um plano real, mas faltavam as partes 2 e 3, como quando usei a opção de plano de consulta real no Management Studio.

Se, por exemplo, eu usasse o Profiler para capturar as informações sobre as chamadas de função, quais eventos eu selecionaria?


Não encontrei uma resposta especificamente relacionada aos planos de consulta, mas criei o perfil de SP: StmtStarting e SP: StmtCompleted e ele mostrou as chamadas de função.

Pedro
fonte

Respostas:

17

E nada sobre as funções. Por que as informações de função estão ausentes no plano real?

Isso ocorre por design, por razões de desempenho.

As funções que contêm BEGINe ENDna definição criam um novo quadro de pilha T-SQL para cada linha de entrada. Em outras palavras, o corpo da função é executado separadamente para cada linha de entrada . Esse fato único explica a maioria dos problemas de desempenho associados às funções escalares e de múltiplas instruções T-SQL (observe que as funções com valor de tabela em linha não usam a BEGIN...ENDsintaxe).

No contexto da sua pergunta, isso resultaria em SHOWPLANsaída completa para cada linha. A saída do plano XML é bastante detalhada e cara de produzir, portanto, produzir uma saída completa para cada linha seria uma má idéia em termos gerais.

Exemplo

Considere a função escalar T-SQL abaixo, criada no banco de dados de exemplo AdventureWorks , que retorna o nome de um produto com seu 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;

Plano de pré-execução

Um plano de pré-execução (plano estimado no SSMS) mostra informações de plano para a instrução pai e chamadas de função aninhadas:

-- Pre-execution plan shows main query and nested function call
SET SHOWPLAN_XML ON;
GO
SELECT dbo.DumbNameLookup(1);
GO
SET SHOWPLAN_XML OFF;

Saída SSMS:

Plano de pré-execução do SSMS

O mesmo XML exibido no SQL Sentry Plan Explorer mostra a natureza aninhada das chamadas com mais clareza:

Plano de pré-execução do PE

Saída pós-execução

O SSMS mostra detalhes apenas da consulta principal quando a saída do plano pós-execução é solicitada:

-- Post-execution plan shows main query only
SET STATISTICS XML ON;
SELECT dbo.DumbNameLookup(1);
SET STATISTICS XML OFF;

Pós-execução do SSMS

O impacto no desempenho de fazer o contrário pode ser mostrado usando a classe de evento Showplan XML Statistics Profile no SQL Server Profiler, usando uma consulta que chama a função várias vezes (uma vez por linha de entrada):

SELECT TOP (5)
    p.ProductID,
    dbo.DumbNameLookup(p.ProductID)
FROM Production.Product AS p;

Saída do Profiler:

Rastreio de saída

Existem cinco planos de pós-execução separados para as execuções de funções e um para a consulta pai. Os cinco planos de função se parecem com isso no painel inferior do criador de perfil:

Planos de funções

O plano de consulta pai é:

Plano pai

A execução da consulta sem a TOP (5)cláusula resulta em um plano de execução completo para cada uma das 504 linhas da tabela Produto. Provavelmente, você pode ver como isso rapidamente sairia do controle com tabelas maiores.

A situação dos gatilhos é revertida. Eles não mostram nenhuma informação do plano de pré-execução, mas incluem um plano de pós-execução. Isso reflete a natureza baseada em conjunto dos gatilhos; cada um é acionado uma vez para todas as linhas afetadas, em vez de uma vez por linha.

Paul White 9
fonte
@PaulWhite: existe alguma boa razão para que os planos de acionamento não sejam mostrados ao solicitar o plano de execução estimado? Parece um recurso ausente útil. Eu posso criar um item de conexão para ele.
usr
@usr - Talvez porque o plano em cache real selecionado pode variar dependendo do número real de linhas, conforme descrito aqui? technet.microsoft.com/en-us/library/…
Martin Smith
@ MartinSmith que pode ser um motivo. Recentemente, um item de conexão para planos de execução de restrições de verificação e fk foi marcado como concluído, então eu esperava que eles fizessem a mesma coisa com gatilhos.
usr
@usr - Este aqui ? 3 meses? Isso deve ser um recorde para uma nova solicitação de recurso!
Martin Smith
@ MartinSmith sim, esse. Foi "consertado" um 1-2 atrás. Eu realmente espero não ter que consultar o armazenamento de consultas. Eu esperava clicar em um botão no SSMS. Na verdade, fiquei surpreso ao ver alguma mudança em uma parte do motor que não foi tocada em anos. Mas talvez não houvesse.
usr