Oracle 19c存储过程本身不支持并行,需通过会话级设置(PARALLEL_DEGREE_POLICY=AUTO)、权限(PARALLEL_QUERY)、SQL级Hint及数据规模(≥10MB)四者协同才能生效。
oracle 19c 中的存储过程本身不支持“配置并行执行”——pl/sql 执行引擎是单线程的,create procedure 语句里没有 prioritize parallel 或类似语法。所谓“让存储过程变快”,实际是让其中嵌套的 sql(尤其是 select、insert、update、delete)走并行执行计划,而 pl/sql 层只是触发者。
为什么直接在存储过程中加 PARALLEL Hint 没用?
常见错误是把并行 Hint 写在存储过程体内的 SQL 字符串里,比如:
CREATE OR REPLACE PROCEDURE proc_load_sales AS BEGIN EXECUTE IMMEDIATE 'SELECT /*+ PARALLEL(t,4) */ * FROM sales t'; END;
这不会生效,原因有三:
-
EXECUTE IMMEDIATE是动态 SQL,Hint 在解析时可能被忽略,尤其当未绑定变量或未启用cursor_sharing=FORCE - 存储过程默认以
AUTHID DEFINER运行,若定义者无PARALLEL_QUERY权限,Hint 直接被跳过 - 更关键的是:即使 Hint 解析成功,若会话未启用并行能力(如未设
PARALLEL_DEGREE_POLICY),Oracle 仍按串行计划执行
真正起作用的三步会话级准备
必须在存储过程执行前或内部显式完成以下设置,且顺序不能错:
- 调用
ALTER SESSION SET PARALLEL_DEGREE_POLICY = 'AUTO'—— 启用自动并行决策(MANUAL仅响应显式 Hint,AUTO还能响应统计信息和负载) - 确保连接字符串含
Enlist=false—— 参与分布式事务(如 MSDTC)会强制禁用并行,哪怕 Hint 和会话设置都正确 - 在 OPEN 连接后、调用存储过程前,执行
ALTER SESSION ENABLE PARALLEL DML(仅对 DML 有效)或至少确认用户有PARALLEL_QUERY权限(GRANT PARALLEL_QUERY ON sales TO myuser)
存储过程内如何安全写并行 SQL?
静态 SQL 比动态 SQL 更可靠;若必须用动态 SQL,需配合绑定与 hint 强制解析:
- 推荐写法(静态):
CREATE OR REPLACE PROCEDURE proc_analyze_big_table AS BEGIN -- 显式指定表别名 + 并行度,避免 /*+ PARALLEL */ 单独出现 INSERT /*+ PARALLEL(sales, 8) */ INTO summary_sales SELECT /*+ PARALLEL(t, 8) */ dept_id, SUM(amount) FROM sales t GROUP BY dept_id; COMMIT; END; - 动态 SQL 补救写法:
EXECUTE IMMEDIATE 'SELECT /*+ PARALLEL(t,4) NO_PARALLEL_INDEX(t, idx_sales_dt) */ * FROM sales t WHERE dt > :1' USING v_cutoff_date;
—— 加NO_PARALLEL_INDEX防止索引扫描意外触发并行,干扰主表并行 - 务必在存储过程末尾加
DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO(如涉及大量 DML),否则后续查询可能因统计信息陈旧而放弃并行
最容易被忽略的性能陷阱
并行不是开关一开就提速,19c 对成本模型极其敏感:
- 表段大小不足 10MB(默认阈值):
SELECT segment_name, bytes/1024/1024 mb FROM dba_segments WHERE segment_name = 'SALES',小于 10 则 Hint 被静默忽略 - 存在阻塞并行的操作:比如
ORDER BY、UNION ALL(非分区场景)、ROWNUM —— 这些会强制收束到单个进程,使并行失效 - 没验证是否真走并行:执行后立刻查
SELECT * FROM V$PQ_SESSTAT WHERE sid = SYS_CONTEXT('USERENV','SID'),若SERVERS_ALLOCATED = 0,说明并行根本没分配
真正耗时的从来不是“怎么写 Hint”,而是确认数据规模、权限链路、会话状态、执行计划四者全部对齐——漏掉任意一环,并行都会安静地退化成串行。


















