¿Cómo obtengo un plan de ejecución de consultas en SQL Server?


338

En Microsoft SQL Server, ¿cómo puedo obtener un plan de ejecución de consultas para una consulta / procedimiento almacenado?


2
¿Cómo cierro la pestaña Plan de ejecución en el estudio de administración del servidor SQL?
Paul McCarthy

2
@Paul Puede presionar Ctrl + R para eso. Cierra toda la sección de resultados, incluidos los mensajes y el plan de ejecución.
Nisarg

Respuestas:


500

Existen varios métodos para obtener un plan de ejecución, el cual dependerá de sus circunstancias. Por lo general, puede usar SQL Server Management Studio para obtener un plan, sin embargo, si por alguna razón no puede ejecutar su consulta en SQL Server Management Studio, puede resultarle útil obtener un plan a través de SQL Server Profiler o inspeccionando el caché del plan

Método 1: uso de SQL Server Management Studio

SQL Server viene con un par de características que hacen que sea muy fácil capturar un plan de ejecución, simplemente asegúrese de que el elemento de menú "Incluir plan de ejecución real" (que se encuentra en el menú "Consulta") esté marcado y ejecute su consulta de forma normal .

Incluir elemento de menú del Plan de ejecución de acciones

Si está tratando de obtener el plan de ejecución para las declaraciones en un procedimiento almacenado, entonces debe ejecutar el procedimiento almacenado de la siguiente manera:

exec p_Example 42

Cuando finalice su consulta, debería ver una pestaña adicional titulada "Plan de ejecución" en el panel de resultados. Si ejecutó muchas declaraciones, es posible que vea muchos planes en esta pestaña.

Captura de pantalla de un plan de ejecución

Desde aquí puede inspeccionar el plan de ejecución en SQL Server Management Studio, o hacer clic con el botón derecho en el plan y seleccionar "Guardar plan de ejecución como ..." para guardar el plan en un archivo en formato XML.

Método 2: usar las opciones de SHOWPLAN

Este método es muy similar al método 1 (de hecho, esto es lo que SQL Server Management Studio hace internamente), sin embargo, lo he incluido para completarlo o si no tiene SQL Server Management Studio disponible.

Antes de ejecutar su consulta, ejecute una de las siguientes declaraciones. La declaración debe ser la única declaración en el lote, es decir, no puede ejecutar otra declaración al mismo tiempo:

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

Estas son opciones de conexión, por lo que solo necesita ejecutar esto una vez por conexión. A partir de este momento, todas las declaraciones ejecutadas estarán acompañadas por un conjunto de resultados adicional que contiene su plan de ejecución en el formato deseado; simplemente ejecute su consulta como lo haría normalmente para ver el plan.

Una vez que haya terminado, puede desactivar esta opción con la siguiente declaración:

SET <<option>> OFF

Comparación de formatos de plan de ejecución

A menos que tenga una fuerte preferencia, mi recomendación es utilizar la STATISTICS XMLopción. Esta opción es equivalente a la opción "Incluir plan de ejecución real" en SQL Server Management Studio y proporciona la mayor cantidad de información en el formato más conveniente.

  • SHOWPLAN_TEXT - Muestra un plan de ejecución estimado basado en texto básico, sin ejecutar la consulta
  • SHOWPLAN_ALL - Muestra un plan de ejecución estimado basado en texto con estimaciones de costos, sin ejecutar la consulta
  • SHOWPLAN_XML- Muestra un plan de ejecución estimado basado en XML con estimaciones de costos, sin ejecutar la consulta. Esto es equivalente a la opción "Mostrar plan de ejecución estimado ..." en SQL Server Management Studio.
  • STATISTICS PROFILE - Ejecuta la consulta y muestra un plan de ejecución real basado en texto.
  • STATISTICS XML- Ejecuta la consulta y muestra un plan de ejecución real basado en XML. Esto es equivalente a la opción "Incluir plan de ejecución real" en SQL Server Management Studio.

Método 3: usar el Analizador de SQL Server

Si no puede ejecutar su consulta directamente (o su consulta no se ejecuta lentamente cuando la ejecuta directamente; recuerde que queremos que un plan de la consulta tenga un mal rendimiento), puede capturar un plan utilizando un seguimiento de SQL Server Profiler. La idea es ejecutar su consulta mientras se ejecuta una traza que captura uno de los eventos de "Showplan".

Tenga en cuenta que dependiendo de la carga puede usar este método en un entorno de producción, sin embargo, obviamente, debe tener precaución. Los mecanismos de creación de perfiles de SQL Server están diseñados para minimizar el impacto en la base de datos, pero esto no significa que no habrá ningún impacto en el rendimiento. También puede tener problemas para filtrar e identificar el plan correcto en su rastreo si su base de datos está bajo uso intensivo. ¡Obviamente, debe consultar con su DBA para ver si están contentos con usted haciendo esto en su preciosa base de datos!

  1. Abra SQL Server Profiler y cree una nueva traza que se conecte a la base de datos deseada en la que desea registrar la traza.
  2. En la pestaña "Selección de eventos", marque "Mostrar todos los eventos", marque la fila "Rendimiento" -> "Showplan XML" y ejecute el seguimiento.
  3. Mientras se ejecuta el seguimiento, haga lo que sea necesario para que se ejecute la consulta de ejecución lenta.
  4. Espere a que se complete la consulta y detenga el rastreo.
  5. Para guardar el seguimiento, haga clic derecho en el plan xml en SQL Server Profiler y seleccione "Extraer datos de eventos ..." para guardar el plan en un archivo en formato XML.

El plan que obtiene es equivalente a la opción "Incluir plan de ejecución real" en SQL Server Management Studio.

Método 4: inspeccionar el caché de consultas

Si no puede ejecutar su consulta directamente y tampoco puede capturar un seguimiento del generador de perfiles, aún puede obtener un plan estimado inspeccionando la caché del plan de consulta SQL.

Inspeccionamos el caché del plan consultando los DMV de SQL Server . La siguiente es una consulta básica que enumerará todos los planes de consulta en caché (como xml) junto con su texto SQL. En la mayoría de las bases de datos, también deberá agregar cláusulas de filtrado adicionales para filtrar los resultados a los planes que le interesen.

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)

Ejecute esta consulta y haga clic en el plan XML para abrir el plan en una nueva ventana. Haga clic con el botón derecho y seleccione "Guardar plan de ejecución como ..." para guardar el plan en un archivo en formato XML.

Notas:

Debido a que hay tantos factores involucrados (que van desde la tabla y el esquema de índice hasta los datos almacenados y las estadísticas de la tabla), siempre debe intentar obtener un plan de ejecución de la base de datos que le interesa (normalmente el que está experimentando un rendimiento problema).

No puede capturar un plan de ejecución para procedimientos almacenados cifrados.

planes de ejecución "reales" versus "estimados"

Un plan de ejecución real es aquel en el que SQL Server realmente ejecuta la consulta, mientras que un plan de ejecución estimado SQL Server resuelve lo que haría sin ejecutar la consulta. Aunque lógicamente equivalente, un plan de ejecución real es mucho más útil ya que contiene detalles y estadísticas adicionales sobre lo que realmente sucedió al ejecutar la consulta. Esto es esencial cuando se diagnostican problemas en los que las estimaciones de los servidores SQL están desactivadas (como cuando las estadísticas no están actualizadas).

¿Cómo interpreto un plan de ejecución de consultas?

Este es un tema lo suficientemente digno para un libro (gratuito) por derecho propio.

Ver también:


8
Una nota para futuros lectores: ponga SET STATISTICS XML ONel principio de la consulta y SET STATISTICS XML OFF|ONlas áreas circundantes que no desea que se muestren en la salida del plan: esto me pareció útil cuando la consulta contiene una iteración (MIENTRAS) que no desea / necesita para ver en el plan de ejecución (de lo contrario, sería demasiado pesado y largo para que SQL SERVER lo muestre).
Roimer

2
@MonsterMMORPG puede usar el método 4 y luego SELECCIONARLO. Por ejemplo, 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) DONDE QUIERE EL TEXTO N '% Su consulta original va aquí%' "); Los% son si solo usa un subconjunto de su consulta.
comentarios

2
@Justin la segunda edición del libro al que se vinculó, para interpretar un plan de ejecución de consultas, data de 2009. ¿Seguiría diciendo que es un recurso realmente bueno para ese propósito en 2016?
Abdul

3
@Abdul El mismo autor, Grant Fritchey, tiene un libro más reciente llamado SQL Server Query Performance Tuning que cubre las versiones más nuevas de SQL Server.
thelem

42

Además de la respuesta integral ya publicada, a veces es útil poder acceder programáticamente al plan de ejecución para extraer información. El código de ejemplo para esto está abajo.

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

StartCaptureDefinición de ejemplo

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

StopCaptureDefinición de ejemplo

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

18

Suponiendo que está utilizando Microsoft SQL Server Management Studio

  • Para el Plan de consulta estimado , puede presionar Ctrl + L o el siguiente botón.

ingrese la descripción de la imagen aquí

  • Para el Plan de consulta real , puede presionar Ctrl + M o el siguiente botón antes de ejecutar la consulta.

ingrese la descripción de la imagen aquí

  • Para el Plan de consulta en vivo , (solo en SSMS 2016) use el siguiente botón antes de ejecutar la consulta.

ingrese la descripción de la imagen aquí


15

Además de los métodos descritos en las respuestas anteriores, también puede usar un visor de plan de ejecución gratuito y una herramienta de optimización de consultas ApexSQL Plan (que me he encontrado recientemente).

Puede instalar e integrar el Plan ApexSQL en SQL Server Management Studio, para que los planes de ejecución se puedan ver directamente desde SSMS.

Visualización de planes de ejecución estimados en el Plan ApexSQL

  1. Haga clic en el botón Nueva consulta en SSMS y pegue el texto de la consulta en la ventana de texto de la consulta. Haga clic derecho y seleccione la opción "Mostrar plan de ejecución estimado" en el menú contextual.

Nuevo botón de consulta en SSMS

  1. Los diagramas del plan de ejecución se mostrarán en la pestaña Plan de ejecución en la sección de resultados. A continuación, haga clic con el botón derecho en el plan de ejecución y en el menú contextual seleccione la opción "Abrir en plan ApexSQL".

Plan de ejecución

  1. El plan de ejecución estimado se abrirá en ApexSQL Plan y se puede analizar para la optimización de consultas.

Plan de ejecución estimado

Ver planes de ejecución reales en el plan ApexSQL

Para ver el plan de ejecución real de una consulta, continúe desde el segundo paso mencionado anteriormente, pero ahora, una vez que se muestra el plan estimado, haga clic en el botón "Actual" de la barra de cinta principal en el plan ApexSQL.

haga clic en el botón "Actual" de la barra de la cinta principal

Una vez que se hace clic en el botón "Actual", se mostrará el plan de ejecución real con una vista previa detallada de los parámetros de costo junto con otros datos del plan de ejecución.

Plan de ejecución real

Puede encontrar más información sobre cómo ver los planes de ejecución siguiendo este enlace .


14

Mi herramienta favorita para obtener y analizar en profundidad los planes de ejecución de consultas es SQL Sentry Plan Explorer . Es mucho más fácil de usar, conveniente y completo para el análisis detallado y la visualización de planes de ejecución que SSMS.

Aquí hay una captura de pantalla de muestra para que tenga una idea de la funcionalidad que ofrece la herramienta:

Captura de pantalla de la ventana de SQL Sentry Plan Explorer

Es solo una de las vistas disponibles en la herramienta. Observe un conjunto de pestañas en la parte inferior de la ventana de la aplicación, que le permite obtener diferentes tipos de representación de su plan de ejecución e información adicional útil también.

Además, no he notado ninguna limitación de su edición gratuita que evite su uso diario o lo obligue a comprar la versión Pro eventualmente. Por lo tanto, si prefiere seguir con la edición gratuita, nada le impide hacerlo.

ACTUALIZACIÓN: (Gracias a Martin Smith ) ¡Plan Explorer ahora es gratis! Consulte http://www.sqlsentry.com/products/plan-explorer/sql-server-query-view para obtener más detalles.


1
¿Quién estaba hablando de herramientas de terceros?
basher

12
@basher: OP no limitó los medios con las herramientas de MS o de alguna otra manera. Entonces, ¿qué te hace pensar que una respuesta que involucra una herramienta de terceros es inapropiada?
Alexander Abakumov

3
Solo bromeaba con la forma en que redactó el comienzo de su respuesta Speaking of third-party toolscuando nadie mencionó herramientas de terceros.
basher

44
@basher: ¡Oh, buena captura! ¡Gracias! He reescrito mi respuesta. Siéntase libre de dar su opinión y / o votarla si lo desea.
Alexander Abakumov


7

Los planes de consulta se pueden obtener de una sesión de eventos extendidos a través del query_post_execution_showplanevento. Aquí hay una sesión de muestra 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

Después de crear la sesión, (en SSMS) vaya al Explorador de objetos y profundice en Administración | Eventos extendidos | Sesiones Haga clic derecho en la sesión "GetExecutionPlan" e iníciela. Haga clic derecho nuevamente y seleccione "Ver datos en vivo".

A continuación, abra una nueva ventana de consulta y ejecute una o más consultas. Aquí hay uno para 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

Después de un momento o dos, debería ver algunos resultados en la pestaña "GetExecutionPlan: Live Data". Haga clic en uno de los eventos query_post_execution_showplan en la cuadrícula y luego haga clic en la pestaña "Plan de consulta" debajo de la cuadrícula. Debería ser similar a esto:

ingrese la descripción de la imagen aquí

EDITAR : El código XEvent y la captura de pantalla se generaron a partir de SQL / SSMS 2012 con SP2. Si está utilizando SQL 2008 / R2, es posible que pueda modificar el script para que se ejecute. Pero esa versión no tiene una GUI, por lo que tendría que extraer el XML del plan de presentación, guardarlo como un archivo * .sqlplan y abrirlo en SSMS. Eso es engorroso. XEvents no existía en SQL 2005 o anterior. Entonces, si no está en SQL 2012 o posterior, le sugiero una de las otras respuestas publicadas aquí.


5

A partir de SQL Server 2016+, se introdujo la función Query Store para monitorear el rendimiento. Proporciona información sobre la elección del plan de consulta y el rendimiento. No es un reemplazo completo de seguimiento o eventos extendidos, pero a medida que evoluciona de una versión a otra, podríamos obtener un almacén de consultas completamente funcional en futuras versiones de SQL Server. El flujo primario de Query Store

  1. Los componentes existentes de SQL Server interactúan con el almacén de consultas utilizando Query Store Manager.
  2. Query Store Manager determina qué Tienda debe usarse y luego pasa la ejecución a esa tienda (Plan o Estadísticas de tiempo de ejecución o Estadísticas de espera de consulta)
    • Tienda de planes: persistencia de la información del plan de ejecución
    • Runtime Stats Store: persistencia de la información de estadísticas de ejecución
    • Query Wait Stats Store: información de estadísticas de espera persistente.
  3. La tienda Plan, Runtime Stats y Wait usa Query Store como una extensión de SQL Server.

ingrese la descripción de la imagen aquí

  1. Habilitación del Almacén de consultas : El Almacén de consultas funciona en el nivel de la base de datos en el servidor.

    • Query Store no está activo para nuevas bases de datos de forma predeterminada.
    • No puede habilitar el almacén de consultas para el maestro o la tempdbbase de datos.
    • DMV disponible

      sys.database_query_store_options (Transact-SQL)

  2. Recopilar información en el almacén de consultas : Recopilamos toda la información disponible de los tres almacenes utilizando el DMV de consultas (vistas de gestión de datos).

    • Almacén de planes de consulta: conserva la información del plan de ejecución y es responsable de capturar toda la información relacionada con la compilación de consultas.

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

    • Runtime Stats Store: persiste la información de las estadísticas de ejecución y es probablemente la tienda actualizada con más frecuencia. Estas estadísticas representan datos de ejecución de consultas.

      sys.query_store_runtime_stats (Transact-SQL)

    • Query Wait Stats Store: persistente y capturando información de estadísticas de espera.

      sys.query_store_wait_stats (Transact-SQL)

NOTA: Query Wait Stats Store solo está disponible en SQL Server 2017+


4

Al igual que con SQL Server Management Studio (ya explicado), también es posible con Datagrip como se explica aquí .

  1. Haga clic con el botón derecho en una instrucción SQL y seleccione Explicar plan.
  2. En el panel Salida, haga clic en Plan.
  3. De forma predeterminada, verá la representación en árbol de la consulta. Para ver el plan de consulta, haga clic en el icono Mostrar visualización o presione Ctrl + Shift + Alt + U

3

Aquí hay una cosa importante que debes saber además de todo lo dicho antes.

Los planes de consulta a menudo son demasiado complejos para ser representados por el tipo de columna XML incorporado que tiene una limitación de 127 niveles de elementos anidados. Esa es una de las razones por las que sys.dm_exec_query_plan puede devolver NULLo incluso arrojar un error en versiones anteriores de MS SQL, por lo que generalmente es más seguro usar sys.dm_exec_text_query_plan . Este último también tiene una característica útil adicional de seleccionar un plan para un estado de cuenta particular en lugar de todo el lote. A continuación, le mostramos cómo lo usa para ver los planes para las declaraciones actualmente en ejecución:

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

Sin embargo, la columna de texto en la tabla resultante no es muy útil en comparación con una columna XML. Para poder hacer clic en el resultado que se abrirá en una pestaña separada como un diagrama, sin tener que guardar su contenido en un archivo, puede usar un pequeño truco (recuerde que no puede usarlo CAST(... AS XML)), aunque esto solo funcionará para un unica fila:

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

2

Como expliqué en este artículo , hay dos tipos de planes de ejecución que puede obtener al usar SQL Server.

Plan de ejecución estimado

El optimizador genera el plan de ejecución estimado sin ejecutar la consulta SQL.

Para obtener el plan de ejecución estimado, debe habilitar la SHOWPLAN_ALLconfiguración antes de ejecutar la consulta.

SET SHOWPLAN_ALL ON

Ahora, al ejecutar la siguiente 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

SQL Server generará el siguiente plan de ejecución estimado:

| 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                 |

Después de ejecutar la consulta, estamos interesados ​​en obtener el plan de ejecución estimado, debe deshabilitar SHOWPLAN_ALL ya que, de lo contrario, la sesión de la base de datos actual solo generará el plan de ejecución estimado en lugar de ejecutar las consultas SQL proporcionadas.

SET SHOWPLAN_ALL OFF

Plan estimado de SQL Server Management Studio

En la aplicación SQL Server Management Studio, puede obtener fácilmente el plan de ejecución estimado para cualquier consulta SQL CTRL+Lpresionando el atajo de teclado.

ingrese la descripción de la imagen aquí

Plan de ejecución real

El optimizador genera el plan de ejecución SQL real cuando ejecuta la consulta SQL. Si las estadísticas de la tabla de la base de datos son precisas, el plan real no debe diferir significativamente del estimado.

Para obtener el plan de ejecución real en SQL Server, debe habilitar la STATISTICS IO, TIME, PROFILEconfiguración, como se ilustra en el siguiente comando SQL:

SET STATISTICS IO, TIME, PROFILE ON

Ahora, al ejecutar la consulta anterior, SQL Server generará el siguiente plan de ejecución:

| 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.

Después de ejecutar la consulta, estamos interesados ​​en obtener el plan de ejecución real, debe deshabilitar la STATISTICS IO, TIME, PROFILE ONconfiguración de esta manera:

SET STATISTICS IO, TIME, PROFILE OFF

Plan real de SQL Server Management Studio

En la aplicación SQL Server Management Studio, puede obtener fácilmente el plan de ejecución estimado para cualquier consulta SQL CTRL+Mpresionando el atajo de teclado.

ingrese la descripción de la imagen aquí

Para obtener más detalles sobre cómo obtener un plan de ejecución al usar SQL Server, consulte este artículo .


2

También puede hacerlo a través de powershell usando SET STATISTICS XML ON para obtener el plan real. Lo escribí para que combine planes de múltiples estados en un solo plan;

    ########## 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()

0

Explicar el plan de ejecución puede ser muy detallado y lleva bastante tiempo de lectura, pero en resumen, si usa 'explicar' antes de la consulta, debería proporcionarle mucha información, incluidas las partes que se ejecutaron primero y así. si quieres leer un poco más de detalles sobre esto, compilé un pequeño blog sobre esto que también te indica las referencias correctas. https://medium.com/swlh/jetbrains-datagrip-explain-plan-ac406772c470

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.