Oracle默认不为GROUP BY启用并行,因受表并行属性、统计信息、ROWNUM/FOR UPDATE、函数分组、NULL值等硬性条件限制;需检查执行计划是否有PX操作符及v$session_longops确认实际并行状态。

GROUP BY 为什么让并行执行计划“自动消失”
Oracle 默认不为 GROUP BY 启用并行,不是优化器偷懒,而是它被一连串硬性条件卡住了——只要其中任意一条不满足,并行就直接退化成串行。最常见的情况是:表没开并行、统计信息过期、SQL里夹了 ROWNUM 或 FOR UPDATE,甚至只是分组字段里有个 UPPER(name),都会让执行计划里彻底看不到 PX 操作符。
哪些写法会悄悄禁用并行
这些看似无害的操作,实际是并行的“隐形杀手”:
-
GROUP BY UPPER(name):函数包裹导致无法做并行哈希分发,优化器只能退回到串行SORT GROUP BY - 查询中含
ROWNUM <= 10或FOR UPDATE:Oracle 明确禁止在这些语义下启用并行 - 目标表的
PARALLEL属性为DISABLE(默认值),或ALTER TABLE ... PARALLEL 1:并行度设为 1 等同于关闭 - 统计信息陈旧,比如
LAST_ANALYZED是半年前的:优化器误判数据量小,认为并行开销大于收益 - 分组字段存在大量
NULL值:触发低效的哈希重分布,优化器主动放弃并行路径
怎么确认并行到底有没有生效
别信直觉,看执行计划里的真实信号:
- 查
v$session_longops:运行时执行SELECT * FROM v$session_longops WHERE opname LIKE '%Group%',若sofar = totalwork且没出现PX相关操作,基本就是串行了 - EXPLAIN PLAN 中
Operation列只显示HASH GROUP BY或SORT GROUP BY,没有PX COORDINATOR/PX SEND等字样 -
Cost值远高于预期,且Bytes和Cardinality严重偏离真实过滤后行数
强制并行但又不翻车的关键控制点
加 /*+ PARALLEL(t, 4) */ 不等于万事大吉,漏掉下面任一环节都可能白忙:
- 必须搭配
USE_HASH_AGGREGATION提示:绕过内存不足时自动降级为SORT GROUP BY的逻辑,强制走内存哈希聚合 - 分组字段不能有隐式转换:比如
WHERE id = '123'(id 是 NUMBER)会导致索引失效,连带并行路径被放弃 - 分区表上 GROUP BY 若未按分区键分组,会触发
PX SEND QC (RANDOM)—— 跨分区重分布,网络和协调开销反而比串行还高 - 闪回数据归档(Flashback Data Archive)开启时,
PARALLEL可能被静默禁用,需查v$session_longops确认实际执行状态
真正难的不是加提示,而是让整个执行链路——从对象属性、统计信息、SQL写法到运行时环境——全部对齐并行的前提。少一个齿轮,整条流水线就卡住。


















