giip
SES Proposal
SQL ServerMedium性能パラメータ監視

Causes and Checks for High CXPACKET Waits in SQL Server

Published 2026-08-13 · Updated 2026-08-13 · Last Verified 2026-08-13

Answer

CXPACKET is a wait type representing synchronization between tasks in a parallel query, and a large value by itself is not evidence of a problem. First check its share of total waits using `sys.dm_os_wait_stats`, and on SQL Server 2016 SP2 / 2017 CU3 and later, distinguish it from CXCONSUMER, into which harmless waits were split out. Whether there is actual impact should be judged by watching real-time waits with `sys.dm_os_waiting_tasks` and checking whether they are tied to an actually slow query.

Applicability of This Document

ProductSQL Server / Amazon RDS for SQL Server / Azure SQL Managed Instance
Verified VersionsSQL Server 2008 and later (CXCONSUMER requires SQL Server 2016 SP2 / 2017 CU3 or later)
EnvironmentOn-premises, EC2, Amazon RDS, Azure
Required PermissionsThe read-only SQL requires VIEW SERVER STATE. `DBCC SQLPERF(..., CLEAR)` requires server-level permission
Execution ImpactThe read-only SQL makes no changes. Clearing wait statistics resets the instance-wide statistics
RestartNot required
Last Verified2026-08-13

Ready-to-Run Commands

Top 20 wait types (excluding idle-type waits)Read-only
対象
SQL Server 2008 and later / Amazon RDS for SQL Server
権限
VIEW SERVER STATE
変更作業
None (read-only)
Production実行
Safe to run
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: VIEW SERVER STATE
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SELECT TOP (20)
    ws.wait_type,
    ws.waiting_tasks_count,
    ws.wait_time_ms,
    ws.wait_time_ms - ws.signal_wait_time_ms AS resource_wait_ms,
    ws.signal_wait_time_ms,
    ws.max_wait_time_ms,
    CAST(100.0 * ws.wait_time_ms
         / NULLIF(SUM(ws.wait_time_ms) OVER (), 0) AS decimal(5, 2)) AS pct_of_total
FROM sys.dm_os_wait_stats AS ws
WHERE ws.waiting_tasks_count > 0
  -- 常時発生するアイドル・バックグラウンド待機を除外する
  AND ws.wait_type NOT IN (
        'CLR_SEMAPHORE', 'LAZYWRITER_SLEEP', 'RESOURCE_QUEUE', 'SLEEP_TASK',
        'SLEEP_SYSTEMTASK', 'SQLTRACE_BUFFER_FLUSH', 'WAITFOR', 'LOGMGR_QUEUE',
        'CHECKPOINT_QUEUE', 'REQUEST_FOR_DEADLOCK_SEARCH', 'XE_TIMER_EVENT',
        'BROKER_TO_FLUSH', 'BROKER_TASK_STOP', 'CLR_MANUAL_EVENT', 'CLR_AUTO_EVENT',
        'DISPATCHER_QUEUE_SEMAPHORE', 'FT_IFTS_SCHEDULER_IDLE_WAIT',
        'XE_DISPATCHER_WAIT', 'XE_DISPATCHER_JOIN', 'ONDEMAND_TASK_QUEUE',
        'BROKER_EVENTHANDLER', 'SLEEP_BPOOL_FLUSH', 'DIRTY_PAGE_POLL',
        'SQLTRACE_INCREMENTAL_FLUSH_SLEEP', 'SP_SERVER_DIAGNOSTICS_SLEEP',
        'QDS_ASYNC_QUEUE', 'HADR_FILESTREAM_IOMGR_IOCOMPLETION'
      )
ORDER BY ws.wait_time_ms DESC;

`sys.dm_os_wait_stats` is a cumulative total since the instance started (or since it was last explicitly cleared). The waits in the exclusion list occur almost constantly as idle-type waits, so without excluding them they would fill up the top results. Even if CXPACKET ranks high in `pct_of_total`, that alone does not indicate a problem.

Check when statistics collection started (instance start time)Read-only
対象
SQL Server 2012 and later (`sqlserver_start_time` column)
権限
VIEW SERVER STATE
変更作業
None (read-only)
Production実行
Safe to run
-- 対象: SQL Server 2012 以降(sqlserver_start_time 列)
-- 権限: VIEW SERVER STATE
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SELECT
    sqlserver_start_time,
    DATEDIFF(HOUR, sqlserver_start_time, GETDATE()) AS uptime_hours
FROM sys.dm_os_sys_info;

Cumulative wait time grows in proportion to uptime. Do not conclude "CXPACKET is high" just by looking at the cumulative total for an instance that has been up for months. You need to look at the value per hour of uptime, or at the interval-based delta described below.

Real-time parallel waits (CXPACKET / CXCONSUMER)Read-only
対象
SQL Server 2008 and later (the `dop` column requires SQL Server 2016 or later)
権限
VIEW SERVER STATE
変更作業
None (read-only)
Production実行
Safe to run
-- 対象: SQL Server 2008 以降(dop 列は SQL Server 2016 以降)
-- 権限: VIEW SERVER STATE
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SELECT
    wt.session_id,
    wt.exec_context_id,
    wt.wait_type,
    wt.wait_duration_ms,
    wt.blocking_session_id,
    wt.blocking_exec_context_id,
    wt.resource_description,
    r.status,
    r.command,
    r.dop,                       -- SQL Server 2016 以降。それ以前の版では列を外すこと
    r.total_elapsed_time,
    txt.text                     AS batch_text
FROM sys.dm_os_waiting_tasks AS wt
LEFT JOIN sys.dm_exec_requests AS r
       ON wt.session_id = r.session_id
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) AS txt
WHERE wt.wait_type LIKE 'CX%'
ORDER BY wt.session_id, wt.exec_context_id;

`exec_context_id = 0` is the coordinator task for the parallel query, and all other values are parallel workers. A coordinator task waiting for a long time suggests the work may be unevenly distributed across workers (skew). The point of this query is to see whether something is waiting right now, not the cumulative total.

Measure wait statistics as a delta over an interval (without clearing them)Read-only
対象
SQL Server 2008 and later / Amazon RDS for SQL Server
権限
VIEW SERVER STATE
変更作業
None (only creates a temp table)
Production実行
Safe to run
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: VIEW SERVER STATE
-- 変更作業: なし(セッションスコープの一時テーブルのみ)
-- Production 実行: 可能
-- 1) 計測開始時点のスナップショットを取る
SELECT wait_type, waiting_tasks_count, wait_time_ms, signal_wait_time_ms
INTO #wait_snapshot
FROM sys.dm_os_wait_stats;

-- 2) 計測したい時間だけ待つ(例: 10分)
WAITFOR DELAY '00:10:00';

-- 3) 差分を取る
SELECT TOP (20)
    w.wait_type,
    w.waiting_tasks_count - s.waiting_tasks_count AS delta_tasks,
    w.wait_time_ms        - s.wait_time_ms        AS delta_wait_ms,
    w.signal_wait_time_ms - s.signal_wait_time_ms AS delta_signal_ms
FROM sys.dm_os_wait_stats AS w
INNER JOIN #wait_snapshot AS s
        ON w.wait_type = s.wait_type
WHERE w.wait_time_ms - s.wait_time_ms > 0
ORDER BY delta_wait_ms DESC;

DROP TABLE #wait_snapshot;

This lets you measure "wait trends during a specific window" without clearing the instance-wide statistics, so prefer this approach in production. It does not affect measurements taken by other operations or monitoring tools.

Clear wait statistics (affects the whole instance)Medium
対象
SQL Server 2008 and later / Amazon RDS for SQL Server
権限
Server-level permission (equivalent to sysadmin)
変更作業
Yes (resets the instance-wide wait statistics to zero)
Production実行
Not recommended — also affects other monitoring tools' measurements
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: サーバーレベルの権限(sysadmin 相当)
-- 変更作業: あり(インスタンス全体の待機統計をリセット)
-- Production 実行: 推奨しない。差分計測で代替できないか先に検討すること
DBCC SQLPERF('sys.dm_os_wait_stats', CLEAR);

No data is lost, but the instance-wide cumulative wait statistics reset to zero. If other monitoring tools reference the same instance, or operations rely on comparison against past values, that baseline disappears. If the delta-measurement approach above meets your needs, use that instead.

How to Read the Results

ColumnMeaningWhat to Check
wait_typeType of waitCheck whether it distinguishes CXPACKET / CXCONSUMER / CXSYNC_PORT, etc.
waiting_tasks_countNumber of times this wait occurredLook at whether it is frequent-but-short or rare-but-long
wait_time_msCumulative wait time (including signal wait)View it relative to instance uptime; the absolute value alone cannot be judged
resource_wait_msResource wait time (wait_time_ms − signal_wait_time_ms)Time actually spent waiting for a resource
signal_wait_time_msCPU scheduling wait timeA high share of the total suggests CPU saturation
pct_of_totalShare of total waits (computed)Even if CXPACKET ranks high, separately confirm whether it is tied to an actually slow query
exec_context_idExecution context ID of the parallel task0 is the coordinator task; if 0 waits for a long time, suspect an uneven workload
wait_duration_msHow long the task is currently waitingWhether any task is waiting a long time right now
dopThe actual degree of parallelism for the request (SQL Server 2016 and later)Whether the degree of parallelism is higher than expected

When to Use This

  • When wait statistics are aggregated, CXPACKET is consistently near the top
  • CPU usage is high, but individual query throughput does not improve
  • The same query takes wildly different amounts of time from one run to the next
  • Overall responsiveness degrades specifically during periods of high concurrency

Possible Causes (Most Likely First)

  1. 01

    This is not actually a problem (parallel execution is working as intended)

    CXPACKET necessarily occurs whenever tasks in a parallel query synchronize with each other. In systems with a lot of analytical queries, it is normal for it to rank high, and ranking high by itself does not indicate a problem. Rule this out first.

  2. 02

    Cost Threshold for Parallelism is too low, causing even small queries to go parallel

    The default value of 5 dates back to a very different era of hardware. In many environments, leaving it at this value causes queries that gain little from parallelism to get parallel plans anyway, adding coordination overhead with little benefit. That said, the right value depends on the workload and should not be changed without measurement.

  3. 03

    Workload is unevenly distributed across parallel workers (skew)

    In partitioned processing, if one worker handles a disproportionate number of rows, the other workers sit idle waiting. You can confirm this from the row-count distribution across threads in the actual execution plan.

  4. 04

    Outdated statistics are causing an unnecessarily large parallel plan to be chosen

    If the estimated row count is larger than the actual count, the estimated cost comes out higher, leading to a parallel plan. The fix here is updating statistics, not changing the degree of parallelism.

  5. 05

    Missing indexes are causing a large scan to be parallelized

    Without a suitable index, the query scans the entire table, and that scan is parallelized. Redesigning the index can eliminate the need for parallel execution altogether.

  6. 06

    The CPU is saturated

    If the share of `signal_wait_time_ms` is high, what's being waited on is not a resource but CPU scheduling order. Lowering the degree of parallelism can help, but the root cause is insufficient CPU or query inefficiency.

Diagnostic Steps

  1. 1

    Get the top wait types

    Read-only

    Check the top 20 by cumulative value to understand where CXPACKET / CXCONSUMER rank.

  2. 2

    Check instance uptime

    Read-only

    Cumulative values scale with uptime. Evaluate them alongside `sqlserver_start_time`.

  3. 3

    Measure a delta for the relevant time window

    Read-only

    Take a snapshot delta during the window when the problem occurs to produce wait trends specific to that window.

  4. 4

    Identify an actually slow query

    Low

    If no slow query exists, no action is needed even if CXPACKET ranks high. Capture the slow query's execution plan before proceeding.

  5. 5

    Observe real-time parallel waits

    Read-only

    Check `CX%` waits with `sys.dm_os_waiting_tasks` and see whether the coordinator task (`exec_context_id = 0`) is waiting for a long time.

  6. 6

    Check statistics and indexes

    Read-only

    Check for a gap between estimated and actual row counts, and for any large scans. Only touch the degree-of-parallelism setting after this.

Solutions

Low-risk action that can be done immediately

  • Confirm whether there is real impact, and do nothing if there is none

    Read-only

    Even if CXPACKET ranks high, no action is needed if every query is meeting its target time. Flattening the ranking of wait statistics is not, by itself, a goal.

  • Update statistics

    Medium

    If an unnecessary parallel plan was chosen due to a row-count estimation gap, updating statistics can change the plan. Check this before touching degree-of-parallelism settings.

  • Restrict the degree of parallelism for a specific query only

    Medium

    If the problem is limited to specific queries, control just those with `OPTION (MAXDOP n)`. This has no effect on the rest of the server.

Change requiring advance review

  • Review Cost Threshold for Parallelism

    Medium

    Consider this once measurement confirms that even small queries are being parallelized. The right value depends on the workload, so decide by comparing execution plans and response times before and after the change.

  • Review MAXDOP

    Medium

    Set an upper bound on the degree of parallelism at the server or database level. Because this changes execution plans server-wide, apply it gradually and measure the effect.

  • Redesign indexes

    Medium

    Where a large scan is being parallelized, adding a suitable index can eliminate the need for parallel execution entirely.

Change involving a restart or service impact

  • Clear wait statistics and re-measure

    Medium

    This resets the instance-wide cumulative statistics and destroys the baseline other monitoring tools rely on. Check first whether delta measurement can serve the same purpose.

  • Control the degree of parallelism with Resource Governor

    Expert Review Required

    You can control the degree of parallelism per workload group, but a misconfiguration can make a specific workload extremely slow. This also has edition restrictions, so it assumes a design review.

!Warnings

  • CXPACKET ranking high among waits is not, by itself, evidence of a problem. The simplistic response of "CXPACKET is high, so set MAXDOP to 1" can drastically slow down analytical workloads that were functioning fine under parallel execution.
  • From SQL Server 2016 SP2 / 2017 CU3 onward, some harmless waits during parallel execution were split out as CXCONSUMER. On these versions and later, do not treat CXCONSUMER the same as CXPACKET.
  • `sys.dm_os_wait_stats` is cumulative since the instance started. Comparing absolute values between instances with different uptimes is meaningless.
  • `DBCC SQLPERF('sys.dm_os_wait_stats', CLEAR)` resets the instance-wide statistics. This also affects any other monitoring tool referencing the same instance.
  • Changing degree-of-parallelism settings affects execution plans across the entire server. Do not make lowering the CXPACKET figure itself the goal.

Differences by Version and Environment

SQL Server 2016 SP2 / 2017 CU3 and laterParallel execution waits were split into CXPACKET and CXCONSUMER. CXCONSUMER represents waits on the consumer-side thread and is generally considered harmless. On these versions and later, evaluate the two separately.
SQL Server 2016 and later`sys.dm_exec_requests` has a `dop` column showing the actual degree of parallelism per request. On earlier versions, remove this column from the query.
SQL Server 2012 and later`sys.dm_os_sys_info.sqlserver_start_time` gives the instance start time, which serves as the baseline for evaluating cumulative wait time.
Amazon RDS for SQL ServerThe wait-statistics DMVs can be queried as-is. Changing MAXDOP or Cost Threshold goes through a DB parameter group, so the procedure differs.

If This Doesn't Resolve It

  • Row-count distribution across threads in the execution plan

    Check the actual execution plan for a significant imbalance in row counts across parallel threads — an imbalance indicates skew.

  • CPU usage and scheduler state

    Check `runnable_tasks_count` in `sys.dm_os_schedulers` to see whether the CPU run queue is backing up.

  • PAGEIOLATCH-family waits

    If I/O waits also rank high alongside CXPACKET, the root cause may lie on the storage side.

  • Memory grant waits (RESOURCE_SEMAPHORE)

    Parallel queries request larger memory grants. If this wait co-occurs, memory also needs to be examined.

Basis and Limitations of This Document

Explanation based on official product documentation

A general procedure based on the public specifications of SQL Server's `sys.dm_os_wait_stats`, `sys.dm_os_waiting_tasks`, `sys.dm_exec_requests`, `sys.dm_os_sys_info`, and `DBCC SQLPERF`. The CXCONSUMER introduction is described as SQL Server 2016 SP2 / 2017 CU3, but check the version details of the target environment for the exact applicable build. It does not include measured values from any specific customer.

FAQ

Is a high volume of CXPACKET waits a problem?

Ranking high among waits is not, by itself, a problem. CXPACKET is evidence that parallel queries are running, and it is normal for it to rank high in environments with a lot of analytical workloads. It only becomes something to act on once there is a process actually exceeding its target time that is tied to this parallel wait.

What is the difference between CXPACKET and CXCONSUMER?

From SQL Server 2016 SP2 / 2017 CU3 onward, the consumer-side thread wait within parallel execution was split out as CXCONSUMER. CXCONSUMER is generally considered harmless, and treating it the same as CXPACKET leads to overreaction.

Can this be run in production?

The read-only SQL and the delta measurement can both be run in production. `DBCC SQLPERF('sys.dm_os_wait_stats', CLEAR)` resets the instance-wide statistics, so it is not recommended in production — use delta measurement instead.

Does this work on AWS RDS?

The wait-statistics DMVs (`sys.dm_os_wait_stats`, `sys.dm_os_waiting_tasks`) can be queried as-is on Amazon RDS for SQL Server. However, since changing the degree of parallelism goes through a DB parameter group, procedures that assume `sp_configure` cannot be used as written.

What permissions are required?

The read-only SQL requires VIEW SERVER STATE. Clearing wait statistics requires server-level permission (equivalent to sysadmin), which may not be available on a managed service.

How should I interpret the results?

Evaluate by the delta during the window when the problem occurs, not by the ranking of cumulative values. From there, move on to reviewing the degree of parallelism only if the slow query's execution plan has a parallel operator and the row counts are unevenly distributed across threads.

Questions This Document Covers

  • I want to know whether CXPACKET ranking high among waits is abnormal
  • I want to know how to read wait events
  • I want to check parallel query waits while they are happening

What the Risk Labels Mean

  • Read-onlyDoes not change data or settings.
  • LowImpact is limited, but permissions and load should be checked.
  • MediumMay affect performance, locking, or cost.
  • HighMay cause an outage, data loss, or require recovery work.
  • Expert Review RequiredRequires a separate review before applying to production.

GIIP's Scope of Support

Wait events like CXPACKET are a metric best judged not by a single snapshot but by "how does this compare to normal." At GIIP, wait statistics are periodically captured as snapshots and accumulated in a form that supports comparing deltas across time windows. An AI agent detects deviations from the normal pattern and escalates to a human only when tied to an actually slowed-down query, avoiding number-first judgments like "CXPACKET ranks high, so lower the degree of parallelism."

Author & Technical Review

GIIP Production Operations Team

About 30 years of experience in designing, migrating, and operating large-scale web services, SQL Server, Oracle, AWS, and Azure. Experience includes 12 sets of x12large-class AWS RDS for SQL Server environments, an Oracle environment with roughly 120,000 tables, and migrating roughly 3TB from TiDB to Aurora MySQL. AI agents and human experts currently continue to monitor and operate multiple cloud databases and about 30 web services.

Related Knowledge

Related Services

Request an analysis of wait events

If you need to repeat the same checks across multiple environments, we can discuss your entire operations setup.

Request an analysis of wait events

← Back to Knowledge Base