/+ parallel /提示不生效的根本原因在于“能不能用”和“值不值得用”,需满足表并行属性启用、会话并行模式开启、别名严格匹配、dop合理等条件,否则优化器会降级为串行。
直接加 /*+ parallel */ 不一定生效,甚至可能被优化器无视——关键不在“写没写”,而在“能不能用”和“值不值得用”。
为什么 /*+ PARALLEL */ 提示没走并行
常见现象是写了提示但执行计划里仍是 TABLE ACCESS FULL,没有出现 PX 相关操作(如 PX COORDINATOR、PX SEND QC)。根本原因不是语法错,而是以下任一条件不满足:
- 表所在表空间未启用
PARALLEL属性(ALTER TABLE t1 PARALLEL 4或建表时指定) - 会话级未开启并行 DML/DDL 模式(
ALTER SESSION ENABLE PARALLEL DML仅对 DML 有效;查询需确保PARALLEL_DEGREE_POLICY非MANUAL,或显式设PARALLEL_FORCE_LOCAL=FALSE) - 目标表被
NOLOGGING或READ ONLY限制,或存在未提交的事务锁住部分分区 - 优化器估算的并行成本高于串行,尤其当
_parallel_syspls_auto隐含参数关闭且未配DEGREE值时,/*+ PARALLEL */默认行为可能退化为串行
/*+ PARALLEL(t, 4) */ 中的表别名必须严格匹配
提示里的表别名不是可选的“方便写法”,而是强制绑定对象。如果 FROM 子句中用了别名 e,提示就必须写 /*+ PARALLEL(e, 4) */;写成 /*+ PARALLEL(emp, 4) */ 或漏掉别名,Oracle 就无法关联到实际访问路径。
- 复合查询(UNION / WITH)中,每个子句的表都要单独加提示,不能只在最外层加
- 视图内嵌套表时,提示必须作用于视图定义中的原始表名或其别名,而非视图名本身
- 使用同义词时,提示中必须用同义词指向的基表名,而不是同义词名(除非该同义词是 PUBLIC 且已解析)
并行度(DOP)设太高反而拖慢查询
盲目设 DEGREE=32 不等于快 32 倍。真实收益受 I/O 子系统吞吐、CPU 核心数、PGA 内存、以及数据块物理连续性共同制约。
- 当表高水位线(HWM)碎裂严重(比如反复 DELETE + INSERT 后),并行进程会大量读空块,逻辑读暴涨,
db file scattered read等待激增 - DOP 超过
CPU_COUNT × 2后,进程调度开销常超过并行收益,尤其在 OLTP 类混合负载中 - 小表(行数
_small_table_threshold默认约 2% buffer cache)即使加并行,也大概率被降级为串行扫描——这是 Oracle 内部保护机制,不是 bug
真正要检查的三件事,比写提示更重要
很多性能问题卡在前置条件上,而不是提示本身。动手前先确认:
- 查
V$PQ_SESSTAT和V$PX_SESSION,看当前会话是否真有并行 slave 在运行,别只信执行计划里的文字 - 用
SELECT DEGREE, INSTANCES FROM USER_TABLES WHERE TABLE_NAME = 'T1'确认表级并行属性是否生效(DEFAULT不等于“自动启用”) - 跑一次
EXPLAIN PLAN FOR SELECT /*+ PARALLEL(t, 4) */ * FROM t1 WHERE ...,再SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY),重点看IN-OUT列是否为P->P或P->S,否则说明并行流水线根本没搭起来
并行不是银弹。它放大 I/O 能力的同时,也放大了碎片、锁争用和内存压力。真正难的不是让语句“看起来并行”,而是让数据、配置和查询逻辑一起配合得上。











