Como obtenho um plano de execução de consulta no SQL Server?

338

No Microsoft SQL Server, como posso obter um plano de execução de uma consulta / procedimento armazenado?

Justin
fonte
2
Como fecho a guia Plano de Execução no SQL Server Management Studio?
Paul McCarthy
2
@ Paul Você pode pressionar Ctrl + R para isso. Fecha toda a seção de resultados - incluindo as mensagens e o plano de execução.
Nisarg

Respostas:

500

Existem vários métodos para obter um plano de execução, o qual usar dependerá de suas circunstâncias. Geralmente, você pode usar o SQL Server Management Studio para obter um plano; no entanto, se por algum motivo não puder executar sua consulta no SQL Server Management Studio, poderá ser útil obter um plano via SQL Server Profiler ou inspecionando o cache do plano.

Método 1 - usando o SQL Server Management Studio

O SQL Server vem com alguns recursos interessantes que facilitam a captura de um plano de execução, basta verificar se o item de menu "Incluir Plano de Execução Real" (encontrado no menu "Consulta") está marcado e executar sua consulta normalmente. .

Incluir item de menu Plano de Execução de Ação

Se você estiver tentando obter o plano de execução para instruções em um procedimento armazenado, execute o procedimento armazenado, da seguinte maneira:

exec p_Example 42

Quando sua consulta for concluída, você verá uma guia extra intitulada "Plano de execução" no painel de resultados. Se você executou muitas instruções, poderá ver muitos planos exibidos nesta guia.

Captura de tela de um plano de execução

Aqui, você pode inspecionar o plano de execução no SQL Server Management Studio ou clicar com o botão direito do mouse no plano e selecionar "Salvar plano de execução como ..." para salvar o plano em um arquivo no formato XML.

Método 2 - Usando as opções SHOWPLAN

Esse método é muito semelhante ao método 1 (de fato, é o que o SQL Server Management Studio faz internamente); no entanto, eu o incluí por completo ou se você não possui o SQL Server Management Studio disponível.

Antes de executar sua consulta, execute uma das seguintes instruções. A instrução deve ser a única instrução do lote, ou seja, você não pode executar outra instrução ao mesmo tempo:

SET SHOWPLAN_TEXT ON
SET SHOWPLAN_ALL ON
SET SHOWPLAN_XML ON
SET STATISTICS PROFILE ON
SET STATISTICS XML ON -- The is the recommended option to use

Essas são opções de conexão e, portanto, você só precisa executá-la uma vez por conexão. A partir desse ponto, todas as instruções executadas serão acompanhadas por um conjunto de resultados adicional contendo seu plano de execução no formato desejado - basta executar sua consulta como faria normalmente para ver o plano.

Quando terminar, você pode desativar esta opção com a seguinte instrução:

SET <<option>> OFF

Comparação de formatos de plano de execução

A menos que você tenha uma forte preferência, minha recomendação é usar a STATISTICS XMLopção Essa opção é equivalente à opção "Incluir plano de execução real" no SQL Server Management Studio e fornece mais informações no formato mais conveniente.

  • SHOWPLAN_TEXT - Exibe um plano de execução estimado baseado em texto básico, sem executar a consulta
  • SHOWPLAN_ALL - Exibe um plano de execução estimado baseado em texto com estimativas de custo, sem executar a consulta
  • SHOWPLAN_XML- Exibe um plano de execução estimado baseado em XML com estimativas de custo, sem executar a consulta. Isso é equivalente à opção "Exibir plano de execução estimado ..." no SQL Server Management Studio.
  • STATISTICS PROFILE - Executa a consulta e exibe um plano de execução real baseado em texto.
  • STATISTICS XML- Executa a consulta e exibe um plano de execução real baseado em XML. Isso é equivalente à opção "Incluir plano de execução real" no SQL Server Management Studio.

Método 3 - usando o SQL Server Profiler

Se você não puder executar sua consulta diretamente (ou sua consulta não for lenta lentamente quando executada diretamente - lembre-se de que queremos que um plano da consulta tenha um desempenho ruim), você poderá capturar um plano usando um rastreamento do SQL Server Profiler. A idéia é executar sua consulta enquanto um rastreamento que está capturando um dos eventos "Showplan" está em execução.

Observe que, dependendo da carga, você pode usar esse método em um ambiente de produção, no entanto, obviamente, você deve ter cuidado. Os mecanismos de perfis SQL Server são projetados para minimizar o impacto sobre o banco de dados, mas isso não significa que não haverá qualquer impacto no desempenho. Você também pode ter problemas para filtrar e identificar o plano correto em seu rastreio, se o banco de dados estiver sob uso intenso. Obviamente, você deve verificar com seu DBA para ver se eles estão felizes com você fazendo isso em seu precioso banco de dados!

  1. Abra o SQL Server Profiler e crie um novo rastreamento conectando-se ao banco de dados desejado no qual você deseja registrar o rastreamento.
  2. Na guia "Seleção de Eventos", marque "Mostrar todos os eventos", marque a linha "Desempenho" -> "Showplan XML" e execute o rastreamento.
  3. Enquanto o rastreamento estiver em execução, faça o que for necessário para que a consulta de execução lenta seja executada.
  4. Aguarde a conclusão da consulta e pare o rastreamento.
  5. Para salvar o rastreamento, clique com o botão direito do mouse no xml do plano no SQL Server Profiler e selecione "Extrair dados do evento ..." para salvar o plano no arquivo XML.

O plano que você obtém é equivalente à opção "Incluir plano de execução real" no SQL Server Management Studio.

Método 4 - Inspecionando o cache da consulta

Se você não puder executar sua consulta diretamente e também não conseguir capturar um rastreamento do criador de perfil, ainda poderá obter um plano estimado inspecionando o cache do plano de consulta SQL.

Inspecionamos o cache do plano consultando as DMVs do SQL Server . A seguir, é apresentada uma consulta básica que lista todos os planos de consulta em cache (como xml) junto com o texto SQL. Na maioria dos bancos de dados, você também precisará adicionar cláusulas de filtragem adicionais para filtrar os resultados apenas nos planos nos quais está interessado.

SELECT UseCounts, Cacheobjtype, Objtype, TEXT, query_plan
FROM sys.dm_exec_cached_plans 
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
CROSS APPLY sys.dm_exec_query_plan(plan_handle)

Execute esta consulta e clique no XML do plano para abrir o plano em uma nova janela - clique com o botão direito do mouse e selecione "Salvar plano de execução como ..." para salvar o plano em arquivo no formato XML.

Notas:

Como existem muitos fatores envolvidos (desde o esquema da tabela e do índice até os dados armazenados e as estatísticas da tabela), você deve sempre tentar obter um plano de execução do banco de dados em que está interessado (normalmente aquele que está apresentando desempenho) problema).

Você não pode capturar um plano de execução para procedimentos armazenados criptografados.

planos de execução "reais" vs "estimados"

Um plano de execução real é aquele em que o SQL Server realmente executa a consulta, enquanto um plano de execução estimado do SQL Server executa o que ele faria sem executar a consulta. Embora logicamente equivalente, um plano de execução real é muito mais útil, pois contém detalhes e estatísticas adicionais sobre o que realmente aconteceu ao executar a consulta. Isso é essencial ao diagnosticar problemas em que as estimativas dos Servidores SQL estão desativadas (como quando as estatísticas estão desatualizadas).

Como interpreto um plano de execução de consulta?

Esse é um tópico digno o suficiente para um livro (gratuito) por si só.

Veja também:

Justin
fonte
8
Uma observação para futuros leitores: coloque SET STATISTICS XML ONo início da consulta e SET STATISTICS XML OFF|ONas áreas adjacentes que você não deseja que apareçam na saída do plano: achei isso útil quando a consulta contém uma iteração (ENQUANTO) você não deseja / precisa para ver no plano de execução (caso contrário, seria muito pesado e demorado para o SQL SERVER exibi-lo).
Roimer
2
@MonsterMMORPG você pode usar o método 4 e, em seguida, SELECIONAR. Por exemplo, usando <a href=" github.com/StackExchange/dapper-dot-net"> Dapper.net </… > connection.Query <string> ("SELECT query_plan FROM sys.dm_exec_cached_plans CROSS APPLY sys.dm_exec_sql_text (plan_handle ) CROSS APPLY sys.dm_exec_query_plan (plan_handle) WHERE TEXT LIKE N '% Sua consulta original está aqui%' "); Os% são se você usar apenas um subconjunto da sua consulta.
marca
2
@ Justin, a 2ª edição do livro ao qual você vinculou, para interpretar um plano de execução de consultas, é datada de 2009. Você ainda diria que é um recurso realmente bom para esse fim em 2016?
Abdul
3
@Abdul O mesmo autor, Grant Fritchey, tem um livro mais novo chamado SQL Server Query Performance Tuning, que abrange versões mais recentes do SQL Server.
Thelem 17/01
42

Além da resposta abrangente já publicada às vezes, é útil poder acessar o plano de execução programaticamente para extrair informações. Código de exemplo para isso está abaixo.

DECLARE @TraceID INT
EXEC StartCapture @@SPID, @TraceID OUTPUT
EXEC sp_help 'sys.objects' /*<-- Call your stored proc of interest here.*/
EXEC StopCapture @TraceID

StartCaptureDefinição de Exemplo

CREATE PROCEDURE StartCapture
@Spid INT,
@TraceID INT OUTPUT
AS
DECLARE @maxfilesize BIGINT = 5
DECLARE @filepath NVARCHAR(200) = N'C:\trace_' + LEFT(NEWID(),36)

EXEC sp_trace_create @TraceID OUTPUT, 0, @filepath, @maxfilesize, NULL 

exec sp_trace_setevent @TraceID, 122, 1, 1
exec sp_trace_setevent @TraceID, 122, 22, 1
exec sp_trace_setevent @TraceID, 122, 34, 1
exec sp_trace_setevent @TraceID, 122, 51, 1
exec sp_trace_setevent @TraceID, 122, 12, 1
-- filter for spid
EXEC sp_trace_setfilter @TraceID, 12, 0, 0, @Spid
-- start the trace
EXEC sp_trace_setstatus @TraceID, 1

StopCaptureDefinição de Exemplo

CREATE  PROCEDURE StopCapture
@TraceID INT
AS
WITH  XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/showplan' as sql), 
      CTE
     as (SELECT CAST(TextData AS VARCHAR(MAX)) AS TextData,
                ObjectID,
                ObjectName,
                EventSequence,
                /*costs accumulate up the tree so the MAX should be the root*/
                MAX(EstimatedTotalSubtreeCost) AS EstimatedTotalSubtreeCost
         FROM   fn_trace_getinfo(@TraceID) fn
                CROSS APPLY fn_trace_gettable(CAST(value AS NVARCHAR(200)), 1)
                CROSS APPLY (SELECT CAST(TextData AS XML) AS xPlan) x
                CROSS APPLY (SELECT T.relop.value('@EstimatedTotalSubtreeCost',
                                            'float') AS EstimatedTotalSubtreeCost
                             FROM   xPlan.nodes('//sql:RelOp') T(relop)) ca
         WHERE  property = 2
                AND TextData IS NOT NULL
                AND ObjectName not in ( 'StopCapture', 'fn_trace_getinfo' )
         GROUP  BY CAST(TextData AS VARCHAR(MAX)),
                   ObjectID,
                   ObjectName,
                   EventSequence)
SELECT ObjectName,
       SUM(EstimatedTotalSubtreeCost) AS EstimatedTotalSubtreeCost
FROM   CTE
GROUP  BY ObjectID,
          ObjectName  

-- Stop the trace
EXEC sp_trace_setstatus @TraceID, 0
-- Close and delete the trace
EXEC sp_trace_setstatus @TraceID, 2
GO
Martin Smith
fonte
18

Supondo que você esteja usando o Microsoft SQL Server Management Studio

  • Para o Plano de consulta estimado, você pode pressionar Ctrl + L ou o botão a seguir.

insira a descrição da imagem aqui

  • Para o Plano de consulta real , você pode pressionar Ctrl + M ou o botão a seguir antes de executar a consulta.

insira a descrição da imagem aqui

  • Para o Live Query Plan (apenas no SSMS 2016), use o seguinte botão antes de executar a consulta.

insira a descrição da imagem aqui

Tigerjz32
fonte
15

Além dos métodos descritos nas respostas anteriores, você também pode usar um visualizador de plano de execução gratuito e a ferramenta de otimização de consultas ApexSQL Plan (na qual recentemente me deparei).

Você pode instalar e integrar o ApexSQL Plan ao SQL Server Management Studio, para que os planos de execução possam ser visualizados diretamente do SSMS.

Exibindo planos de execução estimados no plano ApexSQL

  1. Clique no botão Nova consulta no SSMS e cole o texto da consulta na janela de texto da consulta. Clique com o botão direito e selecione a opção "Exibir plano de execução estimado" no menu de contexto.

Botão Nova consulta no SSMS

  1. Os diagramas do plano de execução serão mostrados na guia Plano de Execução na seção de resultados. Em seguida, clique com o botão direito do mouse no plano de execução e, no menu de contexto, selecione a opção "Abrir no plano ApexSQL".

Plano de execução

  1. O plano de execução estimado será aberto no ApexSQL Plan e poderá ser analisado para otimização de consultas.

Plano de execução estimado

Exibindo planos de execução reais no plano ApexSQL

Para visualizar o plano de execução real de uma consulta, continue a partir da 2ª etapa mencionada anteriormente, mas agora, depois que o plano Estimado for exibido, clique no botão "Real" na barra de faixa de opções principal do ApexSQL Plan.

clique no botão "Real" na barra de fita principal

Depois que o botão "Real" é clicado, o plano de execução real será mostrado com uma visualização detalhada dos parâmetros de custo, juntamente com outros dados do plano de execução.

Plano de execução real

Mais informações sobre a visualização de planos de execução podem ser encontradas seguindo este link .

Marcin Czyz
fonte
14

Minha ferramenta favorita para obter e analisar profundamente os planos de execução de consultas é o SQL Sentry Plan Explorer . É muito mais fácil de usar, conveniente e abrangente para a análise e visualização detalhadas dos planos de execução do que o SSMS.

Aqui está um exemplo de captura de tela para você ter uma idéia de qual funcionalidade é oferecida pela ferramenta:

Captura de tela da janela do SQL Sentry Plan Explorer

É apenas uma das visualizações disponíveis na ferramenta. Observe um conjunto de guias na parte inferior da janela do aplicativo, que permite obter diferentes tipos de representação do seu plano de execução e também informações adicionais úteis.

Além disso, não notei nenhuma limitação de sua edição gratuita que impeça o uso diário ou o force a comprar a versão Pro eventualmente. Portanto, se você prefere ficar com a edição gratuita, nada o impede de fazê-lo.

ATUALIZAÇÃO: (Obrigado a Martin Smith ) O Plan Explorer agora é gratuito! Consulte http://www.sqlsentry.com/products/plan-explorer/sql-server-query-view para obter detalhes.

Alexander Abakumov
fonte
11
Quem estava falando de ferramentas de terceiros?
basher
12
@ basher: OP não limitou os meios com ferramentas MS ou de alguma outra forma. Então, o que faz você pensar que uma resposta que envolve uma ferramenta de terceiros é inadequada?
Alexander Abakumov
3
Estava apenas brincando com como você formulou o início de sua resposta Speaking of third-party toolsquando ninguém mencionou ferramentas de terceiros.
basher
4
@ basher: Oh, boa captura! Obrigado! Eu reescrevi minha resposta. Por favor, sinta-se livre para dar um feedback e / ou votar se quiser.
Alexander Abakumov
3
BTW existe apenas uma versão agora sqlsentry.com/products/plan-explorer/sql-server-query-view
Martin Smith
7

Os planos de consulta podem ser obtidos em uma sessão de Eventos Estendidos por meio do query_post_execution_showplanevento. Aqui está uma amostra da sessão XEvent:

/*
    Generated via "Query Detail Tracking" template.
*/
CREATE EVENT SESSION [GetExecutionPlan] ON SERVER 
ADD EVENT sqlserver.query_post_execution_showplan(
    ACTION(package0.event_sequence,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)),

/* Remove any of the following events (or include additional events) as desired. */
ADD EVENT sqlserver.error_reported(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.module_end(SET collect_statement=(1)
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.rpc_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sp_statement_completed(SET collect_object_name=(1)
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sql_batch_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sql_statement_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))) 
ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)
GO

Depois de criar a sessão, (no SSMS), vá para o Pesquisador de Objetos e mergulhe em Gerenciamento | Eventos estendidos | Sessões. Clique com o botão direito do mouse na sessão "GetExecutionPlan" e inicie-a. Clique com o botão direito do mouse novamente e selecione "Watch Live Data".

Em seguida, abra uma nova janela de consulta e execute uma ou mais consultas. Aqui está um para o AdventureWorks:

USE AdventureWorks;
GO

SELECT p.Name AS ProductName, 
    NonDiscountSales = (OrderQty * UnitPrice),
    Discounts = ((OrderQty * UnitPrice) * UnitPriceDiscount)
FROM Production.Product AS p 
INNER JOIN Sales.SalesOrderDetail AS sod
    ON p.ProductID = sod.ProductID 
ORDER BY ProductName DESC;
GO

Após alguns instantes, você verá alguns resultados na guia "GetExecutionPlan: Live Data". Clique em um dos eventos query_post_execution_showplan na grade e clique na guia "Plano de consulta" abaixo da grade. Deve ser semelhante a este:

insira a descrição da imagem aqui

EDIT : O código XEvent e a captura de tela foram gerados a partir do SQL / SSMS 2012 com SP2. Se você estiver usando SQL 2008 / R2, você pode ser capaz de ajustar o script para fazê-lo funcionar. Mas essa versão não possui uma GUI, portanto você precisaria extrair o XML do showplan, salvá-lo como um arquivo * .sqlplan e abri-lo no SSMS. Isso é complicado. XEvents não existia no SQL 2005 ou anterior. Portanto, se você não estiver no SQL 2012 ou posterior, sugiro fortemente uma das outras respostas postadas aqui.

Dave Mason
fonte
5

A partir do SQL Server 2016+, o recurso Query Store foi introduzido para monitorar o desempenho. Ele fornece informações sobre a escolha e o desempenho do plano de consulta. Não é uma substituição completa de eventos de rastreamento ou estendidos, mas, à medida que evolui de versão para versão, podemos obter um armazenamento de consultas totalmente funcional em versões futuras do SQL Server. O fluxo primário do Query Store

  1. Os componentes existentes do SQL Server interagem com o armazenamento de consultas utilizando o Query Store Manager.
  2. O Gerenciador de Consultas de Consultas determina qual Loja deve ser usada e passa a execução para essa loja (Planejar ou Runtime Stats ou Query Wait Stats)
    • Armazenar plano - Persistir nas informações do plano de execução
    • Armazenamento de Estatísticas de Tempo de Execução - Persistindo nas Informações Estatísticas de Execução
    • Armazenamento de estatísticas de espera de consulta - informações persistentes sobre estatísticas de espera.
  3. O armazenamento Planejar, Estatísticas de Tempo de Execução e Esperar usa o Query Store como uma extensão do SQL Server.

insira a descrição da imagem aqui

  1. Habilitando o Query Store : O Query Store funciona no nível do banco de dados no servidor.

    • O Query Store não está ativo para novos bancos de dados por padrão.
    • Você não pode habilitar o armazenamento de consultas para o mestre ou o tempdbbanco de dados.
    • DMV disponível

      sys.database_query_store_options (Transact-SQL)

  2. Coletar informações no Query Store : Coletamos todas as informações disponíveis das três lojas usando o Query Store DMV (Data Management Views).

    • Armazenamento do plano de consulta: Persiste nas informações do plano de execução e é responsável por capturar todas as informações relacionadas à compilação de consultas.

      sys.query_store_query(Transact-SQL) sys.query_store_plan(Transact-SQL) sys.query_store_query_text(Transact-SQL)

    • Armazenamento de Estatísticas de Tempo de Execução: Persiste nas informações de estatísticas de execução e é provavelmente o armazenamento atualizado com mais freqüência. Essas estatísticas representam dados de execução da consulta.

      sys.query_store_runtime_stats (Transact-SQL)

    • Armazenamento de estatísticas de espera de consulta: persistindo e capturando informações de estatísticas de espera.

      sys.query_store_wait_stats (Transact-SQL)

NOTA: O Armazenamento de Estatísticas de Espera de Consulta está disponível apenas no SQL Server 2017+

vCillusion
fonte
4

Como no SQL Server Management Studio (já explicado), também é possível com o Datagrip, conforme explicado aqui .

  1. Clique com o botão direito do mouse em uma instrução SQL e selecione Explain plan.
  2. No painel Saída, clique em Planejar.
  3. Por padrão, você vê a representação em árvore da consulta. Para ver o plano de consulta, clique no ícone Mostrar Visualização ou pressione Ctrl + Shift + Alt + U
Daan
fonte
3

Aqui está uma coisa importante a saber, além de tudo o que foi dito antes.

Os planos de consulta geralmente são muito complexos para serem representados pelo tipo de coluna XML interno que possui uma limitação de 127 níveis de elementos aninhados. Esse é um dos motivos pelos quais o sys.dm_exec_query_plan pode retornar NULLou até gerar um erro nas versões anteriores do MS SQL, portanto, geralmente é mais seguro usar o sys.dm_exec_text_query_plan . O último também possui um recurso de bônus útil para selecionar um plano para uma declaração específica, em vez de para todo o lote. Veja como você o usa para exibir planos para instruções em execução no momento:

SELECT p.query_plan
FROM sys.dm_exec_requests AS r
OUTER APPLY sys.dm_exec_text_query_plan(
                r.plan_handle,
                r.statement_start_offset,
                r.statement_end_offset) AS p

A coluna de texto na tabela resultante, no entanto, não é muito útil em comparação com uma coluna XML. Para poder clicar no resultado a ser aberto em uma guia separada como um diagrama, sem precisar salvar seu conteúdo em um arquivo, você pode usar um pequeno truque (lembre-se de que não pode apenas usar CAST(... AS XML)), embora isso funcione apenas para um fila unica:

SELECT Tag = 1, Parent = NULL, [ShowPlanXML!1!!XMLTEXT] = query_plan
FROM sys.dm_exec_text_query_plan(
                -- set these variables or copy values
                -- from the results of the above query
                @plan_handle,
                @statement_start_offset,
                @statement_end_offset)
FOR XML EXPLICIT
alkoln
fonte
2

Como expliquei neste artigo , existem dois tipos de plano de execução que você pode obter ao usar o SQL Server.

Plano de execução estimado

O plano de execução estimado é gerado pelo Optimizer sem executar a consulta SQL.

Para obter o plano de execução estimado, você precisa habilitar a SHOWPLAN_ALLconfiguração antes de executar a consulta.

DEFINIR SHOWPLAN_ALL ON

Agora, ao executar a seguinte consulta SQL:

SELECT p.id
FROM post p
WHERE EXISTS (
  SELECT 1
  FROM post_comment pc
  WHERE
    pc.post_id = p.id AND
    pc.review = 'Bingo'
)
ORDER BY p.title
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY

O SQL Server irá gerar o seguinte plano estimado de execução:

| NodeId | Parent | LogicalOp            | EstimateRows | EstimateIO  | EstimateCPU | AvgRowSize | TotalSubtreeCost | EstimateExecutions |
|--------|--------|----------------------|--------------|-------------|-------------|------------|------------------|--------------------|
| 1      | 0      | NULL                 | 10           | NULL        | NULL        | NULL       | 0.03374284       | NULL               |
| 2      | 1      | Top                  | 10           | 0           | 3.00E-06    | 15         | 0.03374284       | 1                  |
| 4      | 2      | Distinct Sort        | 30           | 0.01126126  | 0.000504114 | 146        | 0.03373984       | 1                  |
| 5      | 4      | Inner Join           | 46.698       | 0           | 0.00017974  | 146        | 0.02197446       | 1                  |
| 6      | 5      | Clustered Index Scan | 43           | 0.004606482 | 0.0007543   | 31         | 0.005360782      | 1                  |
| 7      | 5      | Clustered Index Seek | 1            | 0.003125    | 0.0001581   | 146        | 0.0161733        | 43                 |

Depois de executar a consulta, estamos interessados ​​em obter o plano de execução estimado, é necessário desativar o SHOWPLAN_ALL, pois, caso contrário, a sessão atual do banco de dados gerará apenas o plano de execução estimado em vez de executar as consultas SQL fornecidas.

SET SHOWPLAN_ALL OFF

Plano estimado do SQL Server Management Studio

No aplicativo SQL Server Management Studio, você pode obter facilmente o plano de execução estimado para qualquer consulta SQL pressionando o CTRL+Latalho de tecla.

insira a descrição da imagem aqui

Plano de execução real

O plano de execução real do SQL é gerado pelo Optimizer ao executar a consulta SQL. Se as estatísticas da tabela do banco de dados forem precisas, o plano real não deve diferir significativamente do estimado.

Para obter o plano de execução real no SQL Server, é necessário habilitar as STATISTICS IO, TIME, PROFILEconfigurações, conforme ilustrado pelo seguinte comando SQL:

SET STATISTICS IO, TIME, PROFILE ON

Agora, ao executar a consulta anterior, o SQL Server gerará o seguinte plano de execução:

| Rows | Executes | NodeId | Parent | LogicalOp            | EstimateRows | EstimateIO  | EstimateCPU | AvgRowSize | TotalSubtreeCost |
|------|----------|--------|--------|----------------------|--------------|-------------|-------------|------------|------------------|
| 10   | 1        | 1      | 0      | NULL                 | 10           | NULL        | NULL        | NULL       | 0.03338978       |
| 10   | 1        | 2      | 1      | Top                  | 1.00E+01     | 0           | 3.00E-06    | 15         | 0.03338978       |
| 30   | 1        | 4      | 2      | Distinct Sort        | 30           | 0.01126126  | 0.000478783 | 146        | 0.03338679       |
| 41   | 1        | 5      | 4      | Inner Join           | 44.362       | 0           | 0.00017138  | 146        | 0.02164674       |
| 41   | 1        | 6      | 5      | Clustered Index Scan | 41           | 0.004606482 | 0.0007521   | 31         | 0.005358581      |
| 41   | 41       | 7      | 5      | Clustered Index Seek | 1            | 0.003125    | 0.0001581   | 146        | 0.0158571        |

SQL Server parse and compile time:
   CPU time = 8 ms, elapsed time = 8 ms.

(10 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'post'. Scan count 0, logical reads 116, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'post_comment'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(6 row(s) affected)

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

Depois de executar a consulta, estamos interessados ​​em obter o plano de execução real, é necessário desativar as STATISTICS IO, TIME, PROFILE ONconfigurações como esta:

SET STATISTICS IO, TIME, PROFILE OFF

Plano real do SQL Server Management Studio

No aplicativo SQL Server Management Studio, você pode obter facilmente o plano de execução estimado para qualquer consulta SQL pressionando o CTRL+Matalho de tecla.

insira a descrição da imagem aqui

Para obter mais detalhes sobre como obter um plano de execução ao usar o SQL Server, confira este artigo .

Vlad Mihalcea
fonte
2

Você também pode fazê-lo via PowerShell usando SET STATISTICS XML ON para obter o plano real. Escrevi para mesclar planos de múltiplas instruções em um único plano;

    ########## BEGIN : SCRIPT VARIABLES #####################
    [string]$server = '.\MySQLServer'
    [string]$database = 'MyDatabase'
    [string]$sqlCommand = 'EXEC sp_ExampleSproc'
    [string]$XMLOutputFileName = 'sp_ExampleSproc'
    [string]$XMLOutputPath = 'C:\SQLDumps\ActualPlans\'
    ########## END   : SCRIPT VARIABLES #####################

    #Set up connection
    $connectionString = "Persist Security Info=False;Integrated Security=true;Connection Timeout=0;Initial Catalog=$database;Server=$server"
    $connection = new-object system.data.SqlClient.SQLConnection($connectionString)

    #Set up commands
    $command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)
    $command.CommandTimeout = 0
    $commandXMLActPlanOn = new-object system.data.sqlclient.sqlcommand("SET STATISTICS XML ON",$connection)
    $commandXMLActPlanOff = new-object system.data.sqlclient.sqlcommand("SET STATISTICS XML OFF",$connection)

    $connection.Open()

    #Enable session XML plan
    $result = $commandXMLActPlanOn.ExecuteNonQuery()

    #Execute SP and return resultsets into a dataset
    $adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
    $dataset = New-Object System.Data.DataSet
    $adapter.Fill($dataSet) | Out-Null

    #Set up output file name and path
    [string]$fileNameDateStamp = get-date -f yyyyMMdd_HHmmss
    [string]$XMLOutputFilePath = "$XMLOutputPath$XMLOutputFileName`_$fileNameDateStamp.sqlplan"

    #Pull XML plans out of dataset and merge into one multi-statement plan
    [int]$cntr = 1
    ForEach($table in $dataset.Tables)
    {
            if($table.Columns[0].ColumnName -eq "Microsoft SQL Server 2005 XML Showplan")
            {

                [string]$fullXMLPlan = $Table.rows[0]."Microsoft SQL Server 2005 XML Showplan"

                if($cntr -eq 1)
                    {

                    [regex]$rx = "\<ShowPlanXML xmlns\=.{1,}\<Statements\>"
                    [string]$startXMLPlan = $rx.Match($fullXMLPlan).Value
                    [regex]$rx = "\<\/Statements\>.{1,}\<\/ShowPlanXML\>"
                    [string]$endXMLPlan = $rx.Match($fullXMLPlan).Value

                    $startXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

                    }

                [regex]$rx = "\<StmtSimple.{1,}\<\/StmtSimple\>"
                [string]$bodyXMLPlan = $rx.Match($fullXMLPlan).Value

                $bodyXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

                $cntr += 1
            } 
    }

    $endXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

    #Disable session XML plan
    $result = $commandXMLActPlanOff.ExecuteNonQuery()

    $connection.Close()
Guy Bishop
fonte
0

Explicar o plano de execução pode ser muito detalhado e leva bastante tempo para ler, mas, em resumo, se você usar 'explanar' antes da consulta, ele deverá fornecer muitas informações, incluindo quais partes foram executadas primeiro e assim por diante. se você quiser ler um pouco mais de detalhes sobre isso, compilei um pequeno blog sobre isso, que também indica as referências corretas. https://medium.com/swlh/jetbrains-datagrip-explain-plan-ac406772c470

Abd Rmdn
fonte