oracle中group by默认不走并行,因需同时满足表可并行、优化器判定收益大于开销、无rownum/for update等阻塞操作,且统计信息准确、无大量null值干扰;否则执行计划无px操作符,仅显示hash/sort group by。

分组聚合(GROUP BY)在数据中台、实时报表和数字孪生场景中极易成为性能瓶颈,尤其当涉及千万级宽表、多列分组或嵌套分析函数时。单纯加索引往往无效——因为聚合本身不走索引扫描,而全表扫描+排序+哈希分组的资源开销会随数据量非线性上升。真正有效的解法是让 Oracle 主动并行化处理,并控制执行路径不退化。
为什么 GROUP BY 默认不走并行?
Oracle 对 GROUP BY 启用并行的前提很苛刻:必须满足「表可并行」+「优化器判定收益大于开销」+「无阻塞操作干扰」。常见阻断点包括:
- 查询中含
ROWNUM、FOR UPDATE或未显式启用并行的视图 - 目标表的
PARALLEL属性为DISABLE(默认值),或degree设为 1 - 统计信息过期,导致优化器误判数据分布,放弃并行计划
- 聚合字段存在大量
NULL值,触发低效的哈希分组重分布
典型现象是执行计划里看不到 PX(Parallel Execution)相关操作符,EXPLAIN PLAN 中 Operation 列全是 HASH GROUP BY 或 SORT GROUP BY,且 Cost 显著高于预估。
强制并行 + 控制执行路径的实用写法
不要依赖优化器自动决策。对关键聚合 SQL,应组合使用对象级并行设置与语句级提示:
- 先确保表已启用并行:
ALTER TABLE sales PARALLEL 4;(注意:该操作不锁表,但需后续DBMS_STATS.GATHER_TABLE_STATS更新统计信息) - 在 SQL 中显式指定并行度:
SELECT /*+ PARALLEL(t, 4) USE_HASH_AGGREGATION */ region, SUM(amount) FROM sales t GROUP BY region; - 避免隐式类型转换干扰并行:检查
GROUP BY字段是否被函数包裹(如UPPER(name)),否则强制退化为串行 - 若聚合后需排序,用
/*+ NO_SORT_GROUP_BY */配合ORDER BY外层,防止优化器重复排序
USE_HASH_AGGREGATION 是关键——它绕过可能因内存不足而降级的 SORT GROUP BY,直接走内存哈希聚合,配合并行能减少 40%~60% 的 CPU 时间。
容易被忽略的并行陷阱
并行不是开得越多越好,尤其在 OLTP 混合负载环境中:
-
PARALLEL提示若未配NO_PARALLEL清理,可能污染后续同会话的其他 SQL,引发 PGA 爆涨或 PX 进程耗尽 - 分区表上
GROUP BY若未按分区键分组,仍会触发跨分区数据重分布(PX SEND QC (RANDOM)),此时并行反而增加网络和协调开销 - 物化视图日志或闪回数据归档(Flashback Data Archive)开启时,
PARALLEL可能被静默禁用,需查v$session_longops确认实际是否并行执行 - AWR 报告中看
SQL ordered by CPU Time,若某条GROUP BYSQL 的Parallel Operations Not Used计数高,说明提示未生效,要回溯是否被绑定变量/视图封装屏蔽
真正起效的并行,必须在 v$pq_tqstat 里看到多行输出,在 AWR 的 Top 5 Timed Events 中 direct path read 占比上升而非 db file scattered read —— 这才是数据真正被分片读取的证据。











