在 Oracle 数据库中,PL/SQL 的 BEGIN...END
块默认是串行执行的,但可以通过以下方法实现并行处理,提升大规模数据操作的性能:
并行 DML(Data Manipulation Language)
在 BEGIN...END
块中启用并行 DML(如 INSERT
、UPDATE
、DELETE
),需显式配置会话参数和语法提示。
启用并行 DML:
ALTER SESSION ENABLE PARALLEL DML;
使用并行提示:
BEGIN
-- 并行插入(DOP=8)
INSERT /*+ PARALLEL(t 8) */ INTO target_table t
SELECT /*+ PARALLEL(s 8) */ * FROM source_table s;
COMMIT;
END;
/
注意事项:
-
必须显式提交(
COMMIT
)才能释放并行资源。 -
监控资源使用(CPU、I/O)避免过载。
并行查询(Parallel Query)
在 SELECT
语句中使用并行提示,加速数据检索(适用于复杂查询或大数据量)。
DECLARE
CURSOR c_emp IS
SELECT /*+ PARALLEL(emp 8) */ employee_id, salary
FROM employees emp
WHERE department_id = 50;
BEGIN
FOR rec IN c_emp LOOP
-- 处理每条记录(例如写入日志)
DBMS_OUTPUT.PUT_LINE(rec.employee_id || ': ' || rec.salary);
END LOOP;
END;
/
并行函数调用(Parallel Pipelined Functions)
CREATE OR REPLACE FUNCTION process_data_parallel
RETURN SYS_REFCURSOR
PARALLEL_ENABLE (PARTITION BY ANY) -- 启用并行
IS
v_cursor SYS_REFCURSOR;
BEGIN
OPEN v_cursor FOR
SELECT /*+ PARALLEL(emp 8) */ employee_id, salary * 1.1 AS new_salary
FROM employees emp;
RETURN v_cursor;
END;
/
-- 调用并行函数
DECLARE
v_result SYS_REFCURSOR;
v_id employees.employee_id%TYPE;
v_salary employees.salary%TYPE;
BEGIN
v_result := process_data_parallel;
LOOP
FETCH v_result INTO v_id, v_salary;
EXIT WHEN v_result%NOTFOUND;
-- 处理数据(例如插入新表)
INSERT INTO salary_updates VALUES (v_id, v_salary);
END LOOP;
CLOSE v_result;
COMMIT;
END;
/
关键配置与注意事项
(1) 参数配置
parallel_max_servers
:控制最大并行进程数。
ALTER SYSTEM SET parallel_max_servers = 64;
parallel_degree_policy
:设置并行策略(AUTO
、MANUAL
、LIMITED
)。
ALTER SESSION SET parallel_degree_policy = AUTO;
(2) 资源监控
查看并行进程状态:
SELECT sid, serial#, qcsid, server_group, server_set, degree
FROM v$px_session;
监控并行任务进度:
SELECT * FROM v$session_longops WHERE opname LIKE '%PARALLEL%';
(3) 事务与锁
-
长事务风险:并行操作可能持有更多锁,需分批提交。
-
死锁预防:避免跨并行任务的资源竞争。
性能对比
场景 | 方法 | 优势 | 适用数据量 |
---|---|---|---|
批量插入/更新 | 并行 DML + APPEND | 直接路径写入,减少 Redo 日志 | 百万级+ |
复杂查询处理 | 并行查询提示 | 加速数据检索 | 十万级+ |
分块数据更新 | DBMS_PARALLEL_EXECUTE | 自动分块,负载均衡 | 千万级+ |
流式数据处理 | 并行管道函数 | 灵活处理复杂逻辑 | 十万级+ |