Oracle的UPDATE语句默认不走并行,需先执行ALTER SESSION ENABLE PARALLEL DML,再配合严格语法的PARALLEL Hint(如UPDATE /+ PARALLEL(t 4) / t SET...),且DOP设置需结合硬件与等待事件谨慎调优。
Oracle的UPDATE语句默认完全不走并行,哪怕你写了/*+ PARALLEL */提示也无效——这是硬性限制,不是配置没调好。
并行DML(PDML)在Oracle中是会话级显式开关,默认关闭。不执行这句,所有UPDATE都强制串行。
ALTER SESSION ENABLE PARALLEL DML必须在UPDATE语句之前单独执行,不能和SQL写在同一PL/SQL块里却放在UPDATE后面SELECT * FROM V$SESSION WHERE SID = SYS_CONTEXT('USERENV', 'SID')查PDML_STATUS字段确认是否为ENABLED
Hint被忽略的最常见原因是语法错位或对象引用错误,Oracle不会报错,只会静默降级。
UPDATE关键字后,例如:UPDATE /*+ PARALLEL(t 4) */ t SET ...,不能写成UPDATE t /*+ PARALLEL(t 4) */ SET ...
UPDATE my_table t SET ...),Hint里必须用这个别名t,不能用原表名my_table
UPDATE my_table t /*+ PARALLEL(t 4) */ SET ...
WHERE EXISTS)时,PARALLEL只作用于主表t,子查询仍串行,别指望整个语句并行化设PARALLEL(t 16)不等于真跑16个PX进程,高DOP在UPDATE场景下极易触发enq: TX - row lock contention或ORA-12838错误。
CPU_COUNT、PARALLEL_THREADS_PER_CPU、PARALLEL_MAX_SERVERS三者共同限制,可用SELECT * FROM V$OSSTAT WHERE STAT_NAME IN ('NUM_CPUS', 'PHYSICAL_MEMORY_BYTES')查硬件上限min(4, CPU_COUNT / 2),再根据AWR报告中gc buffer busy和enq: TX等待事件调整PARTITION子句进一步限定范围,避免跨分区扫描纯PARALLEL UPDATE适合全表或大范围条件更新;但若需根据关联查询结果更新(比如“用表B更新表A”),FORALL批量+并行DML混合用更可控。
BULK COLLECT INTO把驱动数据(如ID+新值)加载到PL/SQL集合,避免游标逐行开销FORALL i IN 1..arr.COUNT UPDATE ... WHERE id = arr(i).id,此时每个UPDATE本身仍是单条,但批量提交减少上下文切换FORALL块所在会话已启用PARALLEL DML,且UPDATE语句含合法PUBLIC提示,则每条UPDATE可能并行执行——但注意:Oracle对FORALL内单条语句的并行支持有限,实测中更推荐将FORALL用于非并行场景,而把PARALLEL留给独立的大范围UPDATECREATE TABLE AS SELECT或INSERT /*+ APPEND */重建表,再RENAME切换,比原地UPDATE快一个数量级并行DML不是开关一开就提速,它把资源争用从I/O搬到了锁和内存结构上。最容易被忽略的是:UPDATE的并行收益高度依赖数据分布——如果WHERE条件命中大量相邻数据块,DOP再高也卡在buffer cache争用上。