并行执行 oracle PL/SQL [重复]

Posted

技术标签:

【中文标题】并行执行 oracle PL/SQL [重复]【英文标题】:Parallel execute oracle PL/SQL [duplicate] 【发布时间】:2016-09-15 15:00:39 【问题描述】:

基本上我在 oracle 11g 中有一个包处理文件并在多个表中验证和插入信息, 为了实现这一点,我创建了一个读取文件并传播信息的存储过程,然后我调用多个存储过程来 验证并在每个表中插入数据(每个表一个过程),对于错误,每个 SP 在公共错误表中插入一条记录,最后, 我调用最后一个存储过程来识别常见错误表中是否存在错误并生成包含这些错误的文件。

现在...我正在尝试改进代码以最大程度地减少执行时间,然后我意识到每个验证和插入信息的 SP into table 不依赖于其他 SP 信息,所以我问是否有办法并行调用所有这些 SP。

今天

STORED PROCEDURE charge_file
STORED PROCEDURE insert_table1
STORED PROCEDURE insert_table2
STORED PROCEDURE insert_table3 ...
STORED PROCEDURE return_file

我想做什么

STORED PROCEDURE charge_file
STORED PROCEDURE insert_table1 - STORED PROCEDURE insert_table2 - STORED PROCEDURE insert_table3 ...
STORED PROCEDURE return_file

【问题讨论】:

【参考方案1】:

作为使用parallel_execute的例子:

create table proc_map (proc_id number, proc_name varchar2(64), is_active varchar2(1));

insert into proc_map (proc_id, proc_name, is_active) values (1, 'insert_table1', 'Y');
insert into proc_map (proc_id, proc_name, is_active) values (2, 'insert_table2', 'Y');
insert into proc_map (proc_id, proc_name, is_active) values (3, 'insert_table3', 'Y');


create or replace procedure p_run_proc (ip_start in number, ip_end in number)  is
  v_proc_name proc_map.proc_name%type;
begin
  begin
    select t.proc_name into v_proc_name 
    from proc_map t
    where t.proc_id = ip_start;
  exception
    when no_data_found then null;
    when too_many_rows then null;
  end;

  if v_proc_name is not null
    then
      execute immediate 'begin ' || v_proc_name || '; end;';
  end if;
end;

declare
  v_task_name varchar2(4000) := dbms_parallel_execute.generate_task_name;
  v_sql varchar2(4000);
  v_run varchar2(4000);
  v_thread_count number;
  v_task_status number;
begin
  dbms_parallel_execute.create_task (task_name => v_task_name);

  v_sql := 'select t.proc_id as num_col 
                  ,t.proc_id as num_col
            from proc_map t 
            where t.is_active = ''Y'' 
            order by t.proc_id';

  dbms_parallel_execute.create_chunks_by_SQL (task_name => v_task_name, sql_stmt => v_sql, by_rowid => false);

  v_run := 'begin p_run_proc (ip_start => :start_id, ip_end => :end_id); end;';

  select count(*) into v_thread_count 
  from proc_map t
  where t.is_active = 'Y';

  dbms_parallel_execute.run_task (task_name => v_task_name
                                 ,sql_stmt => v_run
                                 ,language_flag => dbms_sql.native
                                 ,parallel_level => v_thread_count);

  v_task_status := dbms_parallel_execute.task_status (task_name => v_task_name);

  if v_task_status = dbms_parallel_execute.FINISHED
    then
      dbms_parallel_execute.drop_task (task_name => v_task_name);
    else
      raise_application_error (-20001, 'ORA in task ' || v_task_name);
  end if;

end;

【讨论】:

【参考方案2】:

除了DBMS_SCHEDULER 或更旧的DBMS_JOB 之外,PL/SQL 中没有内置的 fork/background 提交。 (DBMS_SCHEDULER 功能更全面,对故障的跟踪也更好。)几年前我写了一个作业控制对象作为一个项目,但老实说我从未使用过它。 www.williamrobertson.net/documents/job-control-object.html

【讨论】:

【参考方案3】:

您可以使用 run_job 或提交。

例如参考以下链接:- http://www.dba-oracle.com/r_execute_pl_sql_in_parallel.htm

【讨论】:

以上是关于并行执行 oracle PL/SQL [重复]的主要内容,如果未能解决你的问题,请参考以下文章

并行运行 PL/SQL 调用并等待执行完成(fork 和 join)

在 PL/SQL 中并行化调用

有没有办法保证 PL/SQL 工作的 DOP?

pl/sql连接Oracle不管执行啥语句都会重复执行这条语句,永不停止,怎么办呀

怎么知道 oracle存储过程是不是执行完

Oracle“并行执行”之二——并行执行类型