如何在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
有许多获取执行计划的方法,取决于您的情况而定。通常可以使用SQL Server Management Studio获取计划,但是如果由于某些原因无法在SQL Server Management Studio中运行查询,则可能会发现通过SQL Server Profiler或检查计划缓存来获取计划非常有用。
方法1-使用SQL Server Management Studio
SQL Server带有一些非常方便的功能,使得捕获执行计划非常容易,只需确保“查询”菜单下的“包括实际执行计划”菜单项已选择,然后像平常一样运行查询即可。
如果您尝试获取存储过程中语句的执行计划,则应执行存储过程,如下所示:
exec p_Example 42
当查询完成后,您应该会在结果窗格中看到一个名为“执行计划”的额外选项卡。如果运行了许多语句,则可能会在此选项卡中显示许多计划。
从这里,您可以在SQL Server Management Studio中检查执行计划,或右键单击计划并选择“保存执行计划为...”将计划保存到XML格式的文件中。
方法2-使用SHOWPLAN选项
此方法与方法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 <
执行计划格式的比较
除非您有明显的偏好,否则我建议使用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中的“包括实际执行计划”选项。
方法3-使用SQL Server Profiler
如果无法直接运行查询(或者当您直接执行查询时查询不运行缓慢-请记住,我们希望获取执行效率低下的查询计划),则可以使用SQL Server Profiler跟踪捕获计划 。想法是在捕获一个“Showplan”事件的跟踪运行时运行查询。
请注意,根据负载情况,您可以在生产环境中使用此方法,但是您应该显然要小心。 SQL Server的专业机制旨在最大限度地减少对数据库的影响,但这并不意味着不会有任何性能影响。 如果您的数据库正在被大量使用,您可能还会遇到过滤和识别正确查询计划的问题。 您显然应该与您的DBA核实他们是否满意您在他们宝贵的数据库上进行此操作!
- 打开SQL Server探查器并创建一个新跟踪,连接到您希望记录跟踪的目标数据库。
- 在“事件选择”选项卡下,选中“显示所有事件”,选中“性能”->“Showplan XML”行并运行跟踪。
- 在跟踪运行时,执行你需要运行的缓慢查询所需的任何操作。
- 等待查询完成并停止跟踪。
- 要保存跟踪,请右键单击SQL Server探查器中的计划XML,并选择“提取事件数据...”以将计划保存为XML格式的文件。
您获得的计划等效于SQL Server Management Studio中的“包括实际执行计划”选项。
方法4-检查查询高速缓存
如果您无法直接运行查询而且也无法捕获探查器跟踪,那么您仍然可以通过检查SQL查询计划高速缓存来获取估计计划。
我们通过查询SQL Server DMVs来检查计划高速缓存。 以下是一个基本查询,它将列出所有缓存的查询计划(作为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格式的文件。
注:
由于涉及的因素如此之多(从表和索引架构到存储的数据和表统计信息),因此您应该始终尝试从您感兴趣的数据库中(通常是遇到性能问题的数据库)获得执行计划。
您无法捕获加密存储过程的执行计划。
“实际” vs“估计”执行计划
实际执行计划是SQL Server实际运行查询的执行计划,而估计执行计划是SQL Server在不执行查询的情况下计算出该怎么做。虽然在逻辑上是等效的,但实际执行计划更有用,因为它包含有关执行查询时实际发生的详细信息和统计信息。在诊断SQL Server估计错误(例如,当统计信息过时时)的问题时,这是必不可少的。
我该如何解释查询执行计划?
这个主题值得写一本(免费)书。