在Microsoft SQL Server如何获得查询/存储过程的查询执行计划?
当前回答
与SQL Server Management Studio(已经解释过了)一样,Datagrip也可以在这里解释。
右键单击SQL语句,并选择Explain plan。 在Output窗格中,单击Plan。 默认情况下,您将看到查询的树表示形式。去看 查询计划时,单击“显示可视化”图标,或按 Ctrl + Shift + Alt + U
其他回答
查询计划可以通过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: Live Data”选项卡中看到一些结果。单击网格中的query_post_execution_showplan事件之一,然后单击网格下面的“Query Plan”选项卡。它应该看起来像这样:
编辑:XEvent代码和屏幕截图是从SQL/SSMS 2012 w/ SP2生成的。如果您使用的是SQL 2008/R2,则可以调整脚本以使其运行。但那个版本没有GUI,所以你需要提取showplan XML,保存为*。并在SSMS中打开。这是麻烦的。XEvents在SQL 2005或更早的版本中并不存在。所以,如果你没有使用SQL 2012或更高版本,我强烈建议你使用这里发布的其他答案之一。
在SQL Server Management Studio:
“Ctrl + M”将生成实际执行计划
“Ctrl + L”将生成估计执行计划
“Shift + Alt + S”为客户端统计
“Ctrl + Alt + P”用于SQL Server Profiler中的跟踪查询。
除了前面回答中描述的方法外,您还可以使用免费的执行计划查看器和查询优化工具ApexSQL plan(我最近碰到了它)。
您可以将ApexSQL计划安装并集成到SQL Server Management Studio中,因此可以直接从SSMS查看执行计划。
在“ApexSQL计划”中查看估计的执行计划
单击SSMS中的新建查询按钮,并将查询文本粘贴到查询文本窗口中。右击并从上下文菜单中选择“Display Estimated Execution Plan”选项。
执行计划图将显示在结果部分的execution plan选项卡中。接下来右键单击执行计划,在上下文菜单中选择“在ApexSQL计划中打开”选项。
预估执行计划将在ApexSQL plan中打开,可以对其进行分析以进行查询优化。
在“ApexSQL计划”中查看实际执行计划
要查看查询的实际执行计划,从前面提到的第二步继续,但是现在,一旦估计计划显示出来,在ApexSQL计划的主带栏中单击“实际”按钮。
一旦点击“实际”按钮,实际执行计划将显示详细的成本参数预览以及其他执行计划数据。
点击此链接可以找到有关查看执行计划的更多信息。
与SQL Server Management Studio(已经解释过了)一样,Datagrip也可以在这里解释。
右键单击SQL语句,并选择Explain plan。 在Output窗格中,单击Plan。 默认情况下,您将看到查询的树表示形式。去看 查询计划时,单击“显示可视化”图标,或按 Ctrl + Shift + Alt + U
除了前面所说的,还有一件重要的事情需要知道。
Query plans are often too complex to be represented by the built-in XML column type which has a limitation of 127 levels of nested elements. That is one of the reasons why sys.dm_exec_query_plan may return NULL or even throw an error in earlier MS SQL versions, so generally it's safer to use sys.dm_exec_text_query_plan instead. The latter also has a useful bonus feature of selecting a plan for a particular statement rather than the whole batch. Here's how you use it to view plans for currently running statements:
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
然而,与XML列相比,结果表中的文本列不是很方便。为了能够单击要在单独的选项卡中作为图表打开的结果,而不必将其内容保存到文件中,您可以使用一个小技巧(记住您不能只使用CAST(…AS XML)),尽管这将只适用于单行:
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
推荐文章
- 在MySQL中的一个查询中更新多个具有不同值的行
- 在SQL中更新多个列
- 如何加速gwt编译器?
- 如何删除表中特定列的第一个字符?
- MySQL OR与IN性能
- 应该……接住环内还是环外?
- 哪个更快/最好?SELECT *或SELECT columnn1, colum2, column3等
- GROUP BY with MAX(DATE)
- 删除id与其他表不匹配的sql行
- 加快R中的循环操作
- 等价的限制和偏移SQL Server?
- 如何从SQL Server中的字符串中剥离所有非字母字符?
- INT和VARCHAR主键之间有真正的性能差异吗?
- 为什么我不能在DELETE语句中使用别名?
- 在SQL Server Management Studio中保存带有标题的结果