You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何提取查询执行计划的CXPACKET等待时间?为何XML存在差异?

问题解答

两种执行计划XML存在差异的原因

  • 手动右键查看的是实际执行计划:该计划包含查询运行时的真实执行数据,包括等待时间、实际扫描行数、CPU耗时等单次执行的具体统计信息,这些数据不会被存入SQL Server的计划缓存。
  • 通过sys.dm_exec_query_stats等DMV获取的执行计划:来自SQL Server的计划缓存,属于预估执行计划(或缓存的计划模板),仅包含查询优化器生成的执行逻辑框架,不会保存单次执行的运行时统计(比如等待时间),因此无法找到CXPACKET等待项。

正确提取CXPACKET等待时间的方法

1. 捕获实际执行计划XML并解析

通过开启SET STATISTICS XML ON获取包含运行时统计的实际执行计划XML,再用XQuery提取CXPACKET等待时间:

-- 开启实际执行计划XML输出
SET STATISTICS XML ON;

-- 执行目标查询
SELECT *
FROM Sales.SalesOrderDetail
ORDER BY CarrierTrackingNumber DESC
OPTION (RECOMPILE);

-- 关闭输出
SET STATISTICS XML OFF;

将返回的XML内容复制后,使用以下SQL解析:

DECLARE @actual_plan XML = '--- 此处粘贴实际执行计划XML内容 ---';

SELECT 
    wait.value('@WaitType', 'NVARCHAR(128)') AS WaitType,
    wait.value('@WaitTimeMs', 'BIGINT') AS WaitTimeMs,
    wait.value('@SignalWaitTimeMs', 'BIGINT') AS SignalWaitTimeMs
FROM @actual_plan.nodes('//WaitStats/Wait') AS ws(wait)
WHERE wait.value('@WaitType', 'NVARCHAR(128)') = 'CXPACKET';

2. 使用扩展事件跟踪

创建扩展事件会话,精准捕获当前会话的CXPACKET等待事件:

-- 创建扩展事件会话
CREATE EVENT SESSION TrackCXPACKETWaits ON SERVER 
ADD EVENT sqlos.wait_completed(
    WHERE wait_type = N'CXPACKET'
    AND sqlserver.session_id = @@SPID) -- 仅跟踪当前会话
ADD TARGET package0.event_file(SET filename=N'C:\Temp\CXPACKET_Trace.xel') -- 指定存储路径
WITH (STARTUP_STATE=OFF);

启动会话、执行查询后,停止会话并读取事件数据:

-- 启动会话
ALTER EVENT SESSION TrackCXPACKETWaits ON SERVER STATE = START;

-- 执行目标查询
SELECT *
FROM Sales.SalesOrderDetail
ORDER BY CarrierTrackingNumber DESC
OPTION (RECOMPILE);

-- 停止会话
ALTER EVENT SESSION TrackCXPACKETWaits ON SERVER STATE = STOP;

-- 查询捕获的等待数据
SELECT 
    event_data.value('(event/data[@name="wait_type"]/text)[1]', 'NVARCHAR(128)') AS WaitType,
    event_data.value('(event/data[@name="duration"]/value)[1]', 'BIGINT')/1000 AS WaitTimeMs, -- 转换为毫秒
    event_data.value('(event/data[@name="signal_duration"]/value)[1]', 'BIGINT')/1000 AS SignalWaitTimeMs
FROM (
    SELECT CONVERT(XML, event_data) AS event_data
    FROM sys.fn_xe_file_target_read_file('C:\Temp\CXPACKET_Trace*.xel', NULL, NULL, NULL)
) AS x;

-- 可选:删除会话
DROP EVENT SESSION TrackCXPACKETWaits ON SERVER;

3. 会话级等待统计差值法

通过对比查询执行前后的会话等待统计,计算CXPACKET等待时间的增量:

-- 记录执行前的CXPACKET等待时间
SELECT wait_time_ms AS Pre_CXPACKET_Wait
INTO #PreWaitStats
FROM sys.dm_exec_session_wait_stats
WHERE session_id = @@SPID AND wait_type = 'CXPACKET';

-- 执行目标查询
SELECT *
FROM Sales.SalesOrderDetail
ORDER BY CarrierTrackingNumber DESC
OPTION (RECOMPILE);

-- 计算执行后的等待时间增量
SELECT 
    s.wait_time_ms - ISNULL(p.Pre_CXPACKET_Wait, 0) AS CXPACKET_WaitTime_Ms
FROM sys.dm_exec_session_wait_stats s
LEFT JOIN #PreWaitStats p ON 1=1
WHERE s.session_id = @@SPID AND s.wait_type = 'CXPACKET';

DROP TABLE #PreWaitStats;

注意:此方法需确保当前会话在查询执行期间无其他并行操作,避免干扰统计结果。

内容的提问来源于stack exchange,提问作者backfischxx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 03:32:09