[英]How do I obtain a Query Execution Plan in SQL Server?
在 Microsoft SQL Server 中,如何获取查询/存储过程的查询执行计划?
有多种获取执行计划的方法,使用哪种方法取决于您的情况。 通常您可以使用 SQL Server Management Studio 来获取计划,但是如果由于某种原因您无法在 SQL Server Management Studio 中运行您的查询,那么您可能会发现能够通过 SQL Server Profiler 或通过检查来获取计划会很有帮助计划缓存。
SQL Server 带有一些简洁的功能,可以很容易地捕获执行计划,只需确保勾选“包括实际执行计划”菜单项(位于“查询”菜单下)并正常运行查询.
如果您试图获取存储过程中语句的执行计划,那么您应该执行存储过程,如下所示:
exec p_Example 42
查询完成后,您应该会在结果窗格中看到一个名为“执行计划”的额外选项卡。 如果您运行了许多语句,那么您可能会看到此选项卡中显示了许多计划。
从这里您可以在 SQL Server Management Studio 中检查执行计划,或右键单击该计划并选择“将执行计划另存为...”以将计划保存为 XML 格式的文件。
此方法与方法 1 非常相似(实际上这是 SQL Server Management Studio 在内部执行的操作),但是为了完整性或如果您没有可用的 SQL Server Management Studio,我将其包含在内。
在您运行查询,运行下面的语句之一。 该语句必须是批处理中唯一的语句,即您不能同时执行另一个语句:
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
这些是连接选项,因此每个连接只需运行一次。 从这一点开始,所有运行的语句都将伴随一个额外的结果集,其中包含所需格式的执行计划 - 只需像往常一样运行查询即可查看计划。
完成后,您可以使用以下语句关闭此选项:
SET <<option>> OFF
除非您有强烈的偏好,否则我的建议是使用STATISTICS XML
选项。 此选项等效于 SQL Server Management Studio 中的“包括实际执行计划”选项,并以最方便的格式提供最多的信息。
SHOWPLAN_TEXT
- 显示基于文本的基本估计执行计划,不执行查询SHOWPLAN_ALL
- 显示带有成本估计的基于文本的估计执行计划,而不执行查询SHOWPLAN_XML
- 显示基于 XML 的估计执行计划和成本估计,而不执行查询。 这相当于 SQL Server Management Studio 中的“显示估计的执行计划...”选项。STATISTICS PROFILE
- 执行查询并显示基于文本的实际执行计划。STATISTICS XML
- 执行查询并显示基于 XML 的实际执行计划。 这相当于 SQL Server Management Studio 中的“包括实际执行计划”选项。如果您不能直接运行您的查询(或者您的查询在您直接执行时不会运行缓慢 - 请记住,我们想要一个执行不佳的查询计划),那么您可以使用 SQL Server Profiler 跟踪捕获一个计划。 这个想法是在捕获“Showplan”事件之一的跟踪正在运行时运行您的查询。
请注意,根据负载,您可以在生产环境中使用此方法,但显然您应该谨慎使用。 SQL Server 分析机制旨在最大限度地减少对数据库的影响,但这并不意味着不会对性能产生任何影响。 如果您的数据库被大量使用,您也可能在过滤和识别跟踪中的正确计划时遇到问题。 您显然应该咨询您的 DBA,看看他们是否对您在他们宝贵的数据库上执行此操作感到满意!
您获得的计划相当于 SQL Server Management Studio 中的“包括实际执行计划”选项。
如果您无法直接运行查询,也无法捕获分析器跟踪,那么您仍然可以通过检查 SQL 查询计划缓存来获取估计计划。
我们通过查询 SQL Server DMV来检查计划缓存。 以下是一个基本查询,它将列出所有缓存的查询计划(作为 xml)及其 SQL 文本。 在大多数数据库上,您还需要添加额外的过滤子句,将结果过滤到您感兴趣的计划。
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)
执行此查询并单击计划 XML 以在新窗口中打开计划 - 右键单击并选择“将执行计划另存为...”以将计划以 XML 格式保存到文件中。
由于涉及的因素太多(从表和索引模式到存储的数据和表统计信息),您应该始终尝试从您感兴趣的数据库中获取执行计划(通常是正在经历性能问题的数据库)问题)。
您无法捕获加密存储过程的执行计划。
实际执行计划是 SQL Server 实际运行查询的地方,而估计的执行计划 SQL Server 计算出它在不执行查询的情况下会做什么。 尽管在逻辑上是等价的,但实际的执行计划更有用,因为它包含有关执行查询时实际发生的情况的其他详细信息和统计信息。 这在诊断 SQL Server 估计值关闭的问题(例如统计数据过时时)时至关重要。
这是一个足以作为(免费) 书本身的主题。
除了已经发布的综合答案之外,有时能够以编程方式访问执行计划以提取信息也很有用。 示例代码如下。
DECLARE @TraceID INT
EXEC StartCapture @@SPID, @TraceID OUTPUT
EXEC sp_help 'sys.objects' /*<-- Call your stored proc of interest here.*/
EXEC StopCapture @TraceID
StartCapture
定义示例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
StopCapture
定义示例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
除了前面答案中描述的方法之外,您还可以使用免费的执行计划查看器和查询优化工具ApexSQL Plan (我最近遇到过)。
您可以将 ApexSQL 计划安装并集成到 SQL Server Management Studio 中,因此可以直接从 SSMS 查看执行计划。
在 ApexSQL Plan 中查看估计的执行计划
在 ApexSQL Plan 中查看实际执行计划
要查看查询的实际执行计划,请从前面提到的第二步继续,但是现在,一旦显示了估计计划,请单击 ApexSQL 计划中主功能区栏中的“实际”按钮。
单击“实际”按钮后,将显示实际执行计划,其中包含成本参数的详细预览以及其他执行计划数据。
点击此链接可以找到有关查看执行计划的更多信息。
我最喜欢的用于获取和深入分析查询执行计划的工具是SQL Sentry Plan Explorer 。 对于执行计划的详细分析和可视化,它比 SSMS 更加人性化、方便和全面。
这是一个示例屏幕截图,可让您了解该工具提供的功能:
它只是工具中可用的视图之一。 请注意应用程序窗口底部的一组选项卡,它们可让您获得不同类型的执行计划表示和有用的附加信息。
此外,我还没有注意到它的免费版有任何限制,无法每天使用它或迫使您最终购买 Pro 版。 因此,如果您更愿意坚持使用免费版,那么没有什么可以禁止您这样做的。
更新:(感谢Martin Smith )Plan Explorer 现在是免费的! 有关详细信息,请参阅http://www.sqlsentry.com/products/plan-explorer/sql-server-query-view 。
可以通过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 事件之一,然后单击网格下方的“查询计划”选项卡。 它应该类似于:
编辑:XEvent 代码和屏幕截图是从 SQL/SSMS 2012 w/SP2 生成的。 如果您使用SQL 2008 / R2,您可能能够调整的脚本,使其运行。 但该版本没有 GUI,因此您必须提取 showplan XML,将其保存为 *.sqlplan 文件并在 SSMS 中打开它。 那很麻烦。 XEvents 在 SQL 2005 或更早版本中不存在。 因此,如果您使用的不是 SQL 2012 或更高版本,我强烈建议您使用此处发布的其他答案之一。
从 SQL Server 2016+ 开始,引入了查询存储功能来监控性能。 它提供了对查询计划选择和性能的洞察。 它不是跟踪或扩展事件的完全替代,但随着它从一个版本到另一个版本的演变,我们可能会在 SQL Server 的未来版本中获得一个功能齐全的查询存储。 Query Store 的主要流程
启用查询存储:查询存储在服务器上的数据库级别工作。
tempdb
数据库启用查询存储。
sys.database_query_store_options
(Transact-SQL)
在查询存储中收集信息:我们使用查询存储 DMV(数据管理视图)从三个存储中收集所有可用信息。
查询计划存储:保存执行计划信息,负责捕获所有与查询编译相关的信息。
sys.query_store_query
(Transact-SQL)sys.query_store_plan
(Transact-SQL)sys.query_store_query_text
(Transact-SQL)
Runtime Stats Store:保存执行统计信息,它可能是更新最频繁的存储。 这些统计信息代表查询执行数据。
sys.query_store_runtime_stats
(Transact-SQL)
Query Wait Stats Store:持久化和捕获等待统计信息。
sys.query_store_wait_stats
(Transact-SQL)
注意:查询等待统计存储仅在 SQL Server 2017+ 中可用
估计的执行计划由优化器生成,无需运行 SQL 查询。
为了获得估计的执行计划,您需要在执行查询之前启用SHOWPLAN_ALL
设置。
SET SHOWPLAN_ALL ON
现在,当执行以下 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 将生成以下估计执行计划:
| 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 |
运行我们感兴趣的查询后,获取估计的执行计划,您需要禁用SHOWPLAN_ALL
as,否则,当前数据库会话将只生成估计的执行计划,而不是执行提供的 SQL 查询。
SET SHOWPLAN_ALL OFF
在 SQL Server Management Studio 应用程序中,您可以通过按CTRL+L
快捷键轻松获取任何 SQL 查询的估计执行计划。
实际的 SQL 执行计划是在运行 SQL 查询时由优化器生成的。 如果数据库表统计准确,那么实际计划应该与估计的计划没有显着差异。
要获取 SQL Server 上的实际执行计划,您需要启用STATISTICS IO, TIME, PROFILE
设置,如以下 SQL 命令所示:
SET STATISTICS IO, TIME, PROFILE ON
现在,在运行前面的查询时,SQL Server 将生成以下执行计划:
| 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.
运行查询后,我们对获取实际执行计划感兴趣,您需要禁用STATISTICS IO, TIME, PROFILE ON
设置,如下所示:
SET STATISTICS IO, TIME, PROFILE OFF
在 SQL Server Management Studio 应用程序中,您可以通过按CTRL+M
快捷键轻松获取任何 SQL 查询的估计执行计划。
像SQL Server Management Studio中(已经说明),也可能与Datagrip作为解释在这里。
- 右键单击 SQL 语句,然后选择解释计划。
- 在“输出”窗格中,单击“计划”。
- 默认情况下,您会看到查询的树形表示。 要查看查询计划,请单击“显示可视化”图标,或按 Ctrl+Shift+Alt+U
您也可以通过 powershell 使用 SET STATISTICS XML ON 来获取实际计划。 我写它是为了将多语句计划合并为一个计划;
########## 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()
除了之前所说的所有内容之外,还有一件重要的事情需要了解。
查询计划通常太复杂,无法由内置的 XML 列类型表示,该类型限制为 127 级嵌套元素。 这就是sys.dm_exec_query_plan在早期 MS SQL 版本中可能返回NULL
甚至抛出错误的原因之一,因此通常使用sys.dm_exec_text_query_plan更安全。 后者还有一个有用的奖励功能,即为特定语句而不是整个批次选择计划。 以下是您如何使用它来查看当前正在运行的语句的计划:
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
解释执行计划可能非常详细并占用相当多的阅读时间,但总而言之,如果您在查询之前使用“解释”,它应该会为您提供很多信息,包括哪些部分最先执行等等。 如果您想阅读更多有关此的详细信息,我编写了一个关于此的小博客,它也为您提供了正确的参考。 https://medium.com/swlh/jetbrains-datagrip-explain-plan-ac406772c470
在 SQL Server Management Studio 中:
“Ctrl + M”将生成实际执行计划
“Ctrl + L”将生成预计执行计划
客户统计的“Shift + Alt + S”
“Ctrl + Alt + P”用于在 SQL Server Profiler 中跟踪查询。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.