如何获得查询执行计划?

落花浮王杯 提交于 2020-03-08 18:01:53

在Microsoft SQL Server中,如何获取查询/存储过程的查询执行计划?


#1楼

我最喜欢的用于获取和深入分析查询执行计划的工具是SQL Sentry Plan Explorer 。 与SSMS相比,它对执行计划的详细分析和可视化更加友好,方便和全面。

这是一个示例屏幕快照,可让您大致了解该工具提供的功能:

这只是该工具中可用的视图之一。 注意应用程序窗口底部的一组选项卡,它使您可以获取不同类型的执行计划表示形式以及有用的其他信息。

此外,我还没有注意到其免费版的任何限制,这些限制会阻止其日常使用或迫使您最终购买Pro版本。 因此,如果您更喜欢免费版,那么没有什么可以阻止您这样做的。

更新:(感谢Martin Smith )Plan Explorer现在是免费的! 有关详细信息,请参见http://www.sqlsentry.com/products/plan-explorer/sql-server-query-view


#2楼

可以通过query_post_execution_showplan事件从扩展事件会话中获取查询计划。 这是一个示例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

创建会话后,(在SSMS中)转到“对象资源管理器”并深入研究“管理” |“管理”。 扩展活动| 会议。 右键单击“ GetExecutionPlan”会话,然后启动它。 再次右键单击它,然后选择“观看实时数据”。

接下来,打开一个新的查询窗口并运行一个或多个查询。 这是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

一两分钟后,您应该在“ GetExecutionPlan:实时数据”选项卡中看到一些结果。 单击网格中的query_post_execution_showplan事件之一,然后单击网格下方的“查询计划”选项卡。 它看起来应该类似于:

编辑 :XEvent代码和屏幕截图是从带有SP2的SQL / SSMS 2012中生成的。 如果您使用SQL 2008 / R2,您可能能够调整的脚本,使其运行。 但是该版本没有GUI,因此您必须提取showplan XML,将其另存为* .sqlplan文件,然后在SSMS中打开它。 太麻烦了 XEvents在SQL 2005或更早版本中不存在。 因此,如果您不使用SQL 2012或更高版本,则强烈建议您在此处发布其他答案之一。


#3楼

假设您正在使用Microsoft SQL Server Management Studio

  • 对于估算查询计划,您可以按Ctrl + L或以下按钮。

  • 对于“ 实际查询计划” ,可以在执行查询之前按Ctrl + M或以下按钮。

  • 对于实时查询计划 ,(仅在SSMS 2016中)在执行查询之前使用以下按钮。


#4楼

除了先前答案中描述的方法之外,您还可以使用免费的执行计划查看器和查询优化工具ApexSQL Plan (我最近接触过)。

您可以将ApexSQL Plan安装并集成到SQL Server Management Studio中,以便可以直接从SSMS查看执行计划。

在ApexSQL计划中查看估计的执行计划

  1. 单击SSMS中的“ 新建查询”按钮,然后将查询文本粘贴到查询文本窗口中。 右键单击并从上下文菜单中选择“显示估计的执行计划”选项。

  1. 执行计划图将显示在结果部分的“执行计划”选项卡中。 接下来,右键单击执行计划,然后在上下文菜单中选择“在ApexSQL计划中打开”选项。

  1. 估计执行计划将在ApexSQL计划中打开,可以对其进行分析以进行查询优化。

在ApexSQL计划中查看实际执行计划

要查看查询的实际执行计划,请从前面提到的第二步继续,但是现在,一旦显示了估算计划,请单击ApexSQL计划主功能区栏中的“实际”按钮。

单击“实际”按钮后,将显示“实际执行计划”,并带有成本参数的详细预览以及其他执行计划数据。

通过以下链接可以找到有关查看执行计划的更多信息。


#5楼

从SQL Server 2016+开始,引入了查询存储功能以监视性能。 它提供有关查询计划选择和性能的见解。 它不是跟踪事件或扩展事件的完整替代品,但是随着版本之间的演进,我们可能会在SQL Server的将来版本中获得功能齐全的查询存储。 查询存储的主要流程

  1. SQL Server现有组件通过利用查询存储管理器与查询存储进行交互。
  2. 查询存储管理器确定应使用哪个存储,然后将执行传递给该存储(计划或运行时统计或查询等待统计)
    • 计划存储-保留执行计划信息
    • 运行时统计信息存储-持久执行统计信息
    • 查询等待统计信息存储-持久等待统计信息。
  3. 计划,运行时统计信息和等待存储使用查询存储作为SQL Server的扩展。

  1. 启用查询存储 :查询存储在服务器上的数据库级别工作。

    • 默认情况下,查询存储对新数据库无效。
    • 您不能为master或tempdb数据库启用查询存储。
    • 可用的DMV

      sys.database_query_store_options (Transact-SQL)

  2. 在查询存储中收集信息 :我们使用查询存储DMV(数据管理视图)从三个存储中收集所有可用信息。

注意:查询等待状态存储仅在SQL Server 2017+中可用

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!