Oracle Parallel Query Waits - PX Deq & Downgrade Analysis
Oracle Parallel Query Waits: PX Deq and Downgrade Analysis
Section titled “Oracle Parallel Query Waits: PX Deq and Downgrade Analysis”Overview
Section titled “Overview”Oracle parallel query (PQ) distributes a SQL operation across multiple server processes — called PX servers (parallel execution servers) — to complete large operations faster by using more CPU and I/O bandwidth simultaneously. When parallel query runs correctly, it provides dramatic performance improvements for large table scans, hash joins, sorts, and aggregations.
However, parallel query introduces a set of wait events that are unique to its coordination overhead. These events appear when:
- PX server processes are being allocated or are communicating
- A parallel query cannot obtain its requested Degree of Parallelism (DOP) and is downgraded or serialized
- PX server processes are waiting for work from the query coordinator or other PX processes
The most important parallel query wait events are:
PX Deq: reap credit — A PX server or the query coordinator is waiting to acknowledge completion of a message dequeue operation. This is coordination overhead between parallel processes.
PX Deq: Slave Session Stats — The query coordinator is waiting for PX slaves to report their session statistics after the parallel operation completes. Elevated time here indicates many parallel operations completing, each generating coordinator overhead.
PX Deq: Execute Reply — A PX slave is waiting to receive an execution reply from another PX server (parallel-to-parallel communication, e.g., in a hash join between two parallel streams).
PX Deq Credit: send blkd — A PX process is blocked trying to send data to its consumer because the consumer’s input queue is full. This indicates unbalanced data distribution between producers and consumers.
enq: PS - contention — Parallel server process allocation: there are not enough PX servers available and sessions are contending for the limited pool.
OS Thread startup — On platforms that use OS threads for parallel execution, this event fires when a new thread needs to be created for a parallel operation. Thread creation latency appears here.
Understanding which of these events is dominant, and at what average wait times, guides the correct resolution.
When This Wait Is a Problem
Section titled “When This Wait Is a Problem”Acceptable: Brief PX Deq: reap credit and PX Deq: Slave Session Stats waits are normal parallel query overhead. They should be present but small relative to the actual query execution events.
Investigate when:
enq: PS - contentionappears in AWR top waits — parallel server pool is exhaustedPX Deq Credit: send blkdis elevated — data distribution skew or buffer sizing issue- Actual DOP in
V$PQ_SESSTATorV$SQLconsistently lower than requested DOP — parallel downgrade is occurring - Parallel operations are taking longer than expected despite no I/O bottleneck
PARALLEL_MAX_SERVERShas been hit (checkV$SYSSTAT“parallel operations not downgraded”)
Critical: Parallel downgrade (where Oracle reduces the DOP from the requested value) can silently cause a 4x query that was supposed to run in 30 seconds to run in 2 minutes. The query finishes without error, but the SLA is missed. Detecting downgrade requires proactive monitoring.
Diagnostic Queries
Section titled “Diagnostic Queries”1. Active Parallel Query Sessions and Their DOP
Section titled “1. Active Parallel Query Sessions and Their DOP”-- Active parallel query operations: coordinator and PX slave sessionsSELECT qc.sid AS coordinator_sid, qc.serial# AS coordinator_serial, qc.username, qc.program, qc.sql_id, qc.event AS coordinator_event, COUNT(px.sid) AS active_px_slaves, -- Requested vs actual DOP MAX(px.server_group) AS server_group, MAX(px.server_set) AS server_setFROM v$session qc JOIN v$px_session px ON qc.sid = px.qcsidWHERE qc.status = 'ACTIVE'GROUP BY qc.sid, qc.serial#, qc.username, qc.program, qc.sql_id, qc.eventORDER BY active_px_slaves DESC;2. V$PX_PROCESS — All PX Server Processes and Their State
Section titled “2. V$PX_PROCESS — All PX Server Processes and Their State”-- All PX server processes: busy vs idleSELECT server_name, status, sid, serial#, pid, spid, sql_id, last_sql_active_timeFROM v$px_processORDER BY status DESC, server_name;3. PX Server Pool Utilization — Detect Pool Exhaustion
Section titled “3. PX Server Pool Utilization — Detect Pool Exhaustion”-- Parallel server pool statisticsSELECT statistic, valueFROM v$pq_sysstatWHERE statistic IN ( 'Servers Busy', 'Servers Idle', 'Servers Started', 'Servers Shutdown', 'Servers Highwater', 'Queries Initiated', 'DFO Trees', 'Local Msgs Sent', 'Distr Msgs Sent', 'Sessions Active' )ORDER BY statistic;4. V$SYSTEM_EVENT — All Parallel Query Wait Events
Section titled “4. V$SYSTEM_EVENT — All Parallel Query Wait Events”-- Parallel query wait events — comprehensive viewSELECT event, wait_class, total_waits, total_timeouts, ROUND(time_waited / 100, 2) AS total_wait_secs, ROUND(average_wait / 100, 4) AS avg_wait_secs, ROUND(average_wait / 100 * 1000, 2) AS avg_wait_msFROM v$system_eventWHERE event LIKE 'PX%' OR event LIKE 'enq: PS%' OR event LIKE 'OS thread startup%' OR event = 'wait for unread message on broadcast channel'ORDER BY total_wait_secs DESC;5. Detect Parallel Downgrade — Requested vs Actual DOP
Section titled “5. Detect Parallel Downgrade — Requested vs Actual DOP”-- SQL statements that were downgraded (requested DOP > actual DOP)SELECT sql_id, sql_text, px_servers_executions, px_servers_max, executions, -- Calculate average actual DOP per execution CASE WHEN executions > 0 AND px_servers_executions > 0 THEN ROUND(px_servers_executions / executions, 1) ELSE 0 END AS avg_actual_px_servers, last_active_time, parsing_schema_nameFROM v$sqlWHERE px_servers_executions > 0 AND executions > 0ORDER BY px_servers_executions DESCFETCH FIRST 30 ROWS ONLY;6. V$PQ_SESSTAT — Per-Session Parallel Query Statistics
Section titled “6. V$PQ_SESSTAT — Per-Session Parallel Query Statistics”-- Parallel query stats for current session (or join to V$SESSION for all)SELECT s.sid, s.username, s.program, pq.statistic, pq.last_query AS last_query_value, pq.session_total AS session_total_valueFROM v$pq_sesstat pq JOIN v$session s ON pq.sid = s.sidWHERE s.username IS NOT NULL AND pq.last_query > 0ORDER BY s.sid, pq.statistic;7. ASH — Historical Parallel Query Wait Analysis
Section titled “7. ASH — Historical Parallel Query Wait Analysis”-- Historical parallel query waits from ASH-- Identify when downgrade or coordination overhead was highestSELECT TO_CHAR(ash.sample_time, 'YYYY-MM-DD HH24:MI') AS sample_minute, ash.event, COUNT(*) AS ash_samples, COUNT(DISTINCT ash.session_id) AS sessions, COUNT(DISTINCT ash.sql_id) AS distinct_sql_statementsFROM v$active_session_history ashWHERE ( ash.event LIKE 'PX%' OR ash.event LIKE 'enq: PS%' OR ash.event = 'OS thread startup' ) AND ash.sample_time > SYSDATE - 1GROUP BY TO_CHAR(ash.sample_time, 'YYYY-MM-DD HH24:MI'), ash.eventORDER BY sample_minute DESC, ash_samples DESC;8. PARALLEL_MAX_SERVERS Setting and Current Usage
Section titled “8. PARALLEL_MAX_SERVERS Setting and Current Usage”-- Parallel configuration parametersSELECT name, value, descriptionFROM v$parameterWHERE name IN ( 'parallel_max_servers', 'parallel_min_servers', 'parallel_degree_policy', 'parallel_degree_limit', 'parallel_servers_target', 'parallel_min_time_threshold', 'parallel_force_local', 'cpu_count')ORDER BY name;Root Causes
Section titled “Root Causes”1. PX Server Pool Exhaustion (enq: PS - contention)
Section titled “1. PX Server Pool Exhaustion (enq: PS - contention)”When all available PX server processes are in use and a new parallel query requests additional servers, the query coordinator must either wait for servers to become free or accept downgrade to a lower DOP. enq: PS - contention fires when sessions wait for PX server processes from the pool.
PARALLEL_MAX_SERVERS defines the ceiling. If Servers Busy in V$PQ_SYSSTAT consistently equals PARALLEL_MAX_SERVERS, the pool is exhausted. Increasing PARALLEL_MAX_SERVERS allows more concurrent parallelism but consumes more memory and CPU.
On systems with PARALLEL_DEGREE_POLICY = AUTO or ADAPTIVE, Oracle manages DOP dynamically and may throttle individual queries to protect system resources.
2. Parallel Downgrade (Silent Performance Degradation)
Section titled “2. Parallel Downgrade (Silent Performance Degradation)”When Oracle cannot provide the full requested DOP due to pool exhaustion or resource limits, it downgrades the query to a lower DOP. The query runs with fewer PX servers than expected — potentially much fewer. For example, a query with PARALLEL 8 hint may run with DOP 2 because only 2 PX servers were available.
Downgrade can also occur due to PARALLEL_SERVERS_TARGET. When the number of busy PX servers exceeds this threshold, Oracle begins downg rading new parallel queries automatically.
3. Producer-Consumer Imbalance (PX Deq Credit: send blkd)
Section titled “3. Producer-Consumer Imbalance (PX Deq Credit: send blkd)”In multi-granule parallel plans, data flows from producer PX servers to consumer PX servers through buffered queues. If one producer generates data much faster than its consumers can process it (due to data skew, partition elimination, or join selectivity differences), the producer’s output queue fills up and the producer blocks on PX Deq Credit: send blkd. This represents work imbalance within the parallel query.
4. PX Coordinator Overhead (PX Deq: Slave Session Stats)
Section titled “4. PX Coordinator Overhead (PX Deq: Slave Session Stats)”When a parallel operation completes, each PX slave must report its statistics back to the query coordinator. This generates PX Deq: Slave Session Stats waits. In systems with very high parallel query concurrency (many small parallel operations completing rapidly), this coordination overhead accumulates. The fix is usually to avoid using parallel query for small operations where the overhead exceeds the benefit.
5. OS Thread Creation Latency (OS Thread startup)
Section titled “5. OS Thread Creation Latency (OS Thread startup)”On platforms that create new OS threads (rather than pre-spawning PX servers) for each parallel operation, OS thread startup records the thread creation latency. This only applies to specific platform/configuration combinations. The fix is to increase PARALLEL_MIN_SERVERS to pre-spawn threads so they are available immediately.
6. PARALLEL_MIN_TIME_THRESHOLD Too Low
Section titled “6. PARALLEL_MIN_TIME_THRESHOLD Too Low”With PARALLEL_DEGREE_POLICY = AUTO, Oracle automatically parallelizes operations that are expected to take longer than PARALLEL_MIN_TIME_THRESHOLD (default: 30 seconds). If this threshold is too low, Oracle parallelizes short-running operations that do not benefit from parallelism — generating PX coordination overhead and consuming PX server slots unnecessarily.
Resolution Steps
Section titled “Resolution Steps”Step 1: Tune PARALLEL_MAX_SERVERS Based on Hardware Capacity
Section titled “Step 1: Tune PARALLEL_MAX_SERVERS Based on Hardware Capacity”-- Check current settingsSHOW PARAMETER parallel_max_servers;SHOW PARAMETER cpu_count;
-- Guideline: PARALLEL_MAX_SERVERS should be at most:-- CPU_COUNT * 2 (for pure parallel workloads)-- CPU_COUNT * (desired concurrent PQ sessions) * avg_DOP
-- Example for 32-core server running 4 concurrent parallel queries at DOP 8:-- 4 * 8 = 32 PX servers needed minimum; set to 64 for headroomALTER SYSTEM SET parallel_max_servers = 64 SCOPE=BOTH;
-- Also set the target (when busy PX servers exceeds this, downgrade begins):ALTER SYSTEM SET parallel_servers_target = 48 SCOPE=BOTH;Step 2: Pre-Spawn PX Servers to Eliminate Thread Startup Overhead
Section titled “Step 2: Pre-Spawn PX Servers to Eliminate Thread Startup Overhead”-- Pre-spawn a base number of PX servers at instance startup-- Eliminates OS thread startup waits for the first wave of parallel queriesALTER SYSTEM SET parallel_min_servers = 16 SCOPE=BOTH;-- Oracle will maintain at least 16 idle PX servers at all timesStep 3: Use PARALLEL_DEGREE_POLICY = AUTO for Adaptive Downgrade
Section titled “Step 3: Use PARALLEL_DEGREE_POLICY = AUTO for Adaptive Downgrade”-- AUTO degree policy: Oracle tunes DOP based on system load-- Prevents runaway parallel queries from exhausting the server poolALTER SYSTEM SET parallel_degree_policy = AUTO SCOPE=BOTH;
-- Set minimum time threshold to avoid parallelizing small operationsALTER SYSTEM SET parallel_min_time_threshold = 30 SCOPE=BOTH; -- 30 seconds
-- Set CPU degree limit to prevent any single query using all CPUsALTER SYSTEM SET parallel_degree_limit = CPU SCOPE=BOTH;Step 4: Fix Data Skew Causing Producer-Consumer Imbalance
Section titled “Step 4: Fix Data Skew Causing Producer-Consumer Imbalance”-- If PX Deq Credit: send blkd is elevated, investigate data distribution-- Check partition data skew:SELECT partition_name, num_rows, blocksFROM dba_tab_partitionsWHERE table_owner = 'HR' AND table_name = 'LARGE_TABLE'ORDER BY num_rows DESC;
-- For skewed hash partitions, consider using subpartitioning-- or choosing a better partition key with higher cardinality
-- Alternatively, use a parallel hint with specific DOP to let Oracle redistribute:SELECT /*+ PARALLEL(t, 4) PQ_DISTRIBUTE(t, HASH, HASH) */ *FROM large_table tJOIN dimension_table d ON t.key = d.key;Step 5: Limit Parallel DOP Per SQL When Pool Is Oversubscribed
Section titled “Step 5: Limit Parallel DOP Per SQL When Pool Is Oversubscribed”-- Use Resource Manager to limit parallel DOP by consumer groupBEGIN DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE( plan => 'MIXED_WORKLOAD_PLAN', group_or_subplan => 'BATCH_USERS', comment => 'Limit batch parallel DOP', parallel_degree_limit_p1 => 4, -- Max DOP = 4 for batch group max_utilization_limit => 40 -- Max 40% CPU );END;/Step 6: Detect and Address Frequent Downgrade
Section titled “Step 6: Detect and Address Frequent Downgrade”-- Check V$SYSSTAT for downgrade frequencySELECT name, valueFROM v$sysstatWHERE name IN ( 'parallel operations not downgraded', 'parallel operations downgraded to serial', 'parallel operations downgraded 75 to 99 pct', 'parallel operations downgraded 50 to 75 pct', 'parallel operations downgraded 25 to 50 pct', 'parallel operations downgraded 1 to 25 pct')ORDER BY name;
-- "parallel operations downgraded to serial" > 0 means full serialization occurred-- This is a critical problem for DWH workloads that depend on parallel executionPrevention & Tuning
Section titled “Prevention & Tuning”Right-size PARALLEL_MAX_SERVERS before production go-live: Profile the parallel workload in a load test, identify peak concurrent DOP demand, and set PARALLEL_MAX_SERVERS with 25% headroom above peak.
Use PARALLEL_SERVERS_TARGET to enable graceful downgrade: Setting PARALLEL_SERVERS_TARGET below PARALLEL_MAX_SERVERS allows Oracle to begin downgrading new queries before the pool is fully exhausted, preventing complete pool starvation.
Monitor “parallel operations downgraded to serial” continuously: This statistic being non-zero means parallel queries are running serially — a silent, significant performance regression. Alert on any increment.
Avoid using parallel query for OLTP workloads: Parallel query is designed for DSS/DWH workloads with large scan operations. Using PARALLEL hints or table-level parallelism on OLTP tables wastes PX server resources and can starve analytical queries of PX servers.
Consider parallel statement queuing (12c+): With PARALLEL_DEGREE_POLICY = AUTO, Oracle can queue parallel queries rather than downgrading them — ensuring full DOP when servers become available:
-- Enable parallel statement queuingALTER SYSTEM SET parallel_degree_policy = AUTO SCOPE=BOTH;-- Queuing is automatically enabled with AUTO policy-- Queries wait in queue for PX servers rather than running at reduced DOPRelated Wait Events
Section titled “Related Wait Events”- PX Deq: Execute Reply — PX slave waiting for a reply from another PX slave (parallel-to-parallel communication in hash joins)
- PX Deq Credit: send blkd — PX producer blocked because consumer’s input queue is full; data distribution skew
- enq: PS - contention — PX server pool allocation contention; pool is exhausted
- db file scattered read — Full table scan reads in parallel query; often the dominant actual work event in parallel scans
- cell multiblock physical read — Exadata equivalent of db file scattered read in parallel query context