[英]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.