create procedure p_insert_1 as
begin
-- remove old data
execute immediate 'truncate table table_1';
-- table_1 data not ready
update table_done set table_1 = 0;
-- prepare new data
insert into table_1 (...) select ...;
-- table_1 data ready
insert into table_done (table_1) values (1);
commit;
end;
create procedure p_main is
l_job_1 number;
l_job_2 number;
--
l_t1_done number;
l_t2_done number;
begin
dbms_job.submit(l_job_1, 'begin p_insert_1; end;');
dbms_job.submit(l_job_2, 'begin p_insert_2; end;');
loop
select table_1, table_2
into l_t1_done, l_t2_done
from table_done;
if l_t1_done = 1 and l_t2_done = 1 then
-- exit the loop
exit;
else
-- tables aren't ready yet; wait 60 seconds and try again
dbms_lock.sleep(60);
end if;
end loop;
-- process data prepared in table_1 and table_2
end;
2条答案
按热度按时间zmeyuzjn1#
有一个选择。
我不会真的使用CTAS --我宁愿 * 提前 * 创建两个表,然后在其中插入行。为什么?因为这种方法使用存储过程--为了执行DDL(也就是CTAS)--需要动态SQL。并不是说这是 * 不可能 * 做到的;相反,但不使用它要简单得多。
我还要创建另一个表(我们称之为
table_done
),它只包含一行两列:table_1
和table_2
,其值可以是0
(表示:该表的数据未就绪)或1
(数据就绪)。此外,我将创建两个看起来相同的存储过程;唯一的区别是它们中的每一个都将行插入到自己的表中:
第三个“main”过程是您要 * 手动 * 运行的过程。它会做什么?创建两个 * 立即 * 运行的一次性数据库作业,每个作业都启动自己的
p_insert
过程,以便并行运行。然后,该过程将(在循环中)检查table_done
中的两列是否都设置为1
,如果是,则继续执行。这只是一个简单的想法我没有亲自测试,所以如果有任何错误,我道歉。另外,
dbms_scheduler
而不是dbms_job
dbms_session.sleep
而不是dbms_lock.sleep
yuvru6vn2#
使用 *SQL并行性 * 而不是 * 进程并发性 *。虽然并行性和并发性这两个词在口语中可以互换,但在Oracle中它们有不同的含义。并行性意味着SQL引擎处理所有的协调工作,包括将工作分解为多个小块,同时运行这些小块,然后在最后重新组合结果。并发意味着用户将创建多个会话并手动处理协调。
对于简单地创建两个表,并行可能比并发更简单、更快。对于并行,您可能只需要并行地创建表。(并且您可能希望在最后将并行重置为无。)
PARALLEL 2
选项指示Oracle在SQL语句运行时同时运行两个服务器进程。您可以轻松地增加该数目,但不要设置得太高,否则将从其他会话窃取太多资源。DBMS_SCHEDULER和其他并发机制非常强大和有用,但我建议尽可能避免使用它们。运行和监视调度程序作业可能比前面的代码复杂得多。(尽管您可能仍然需要偶尔使用OEM SQL Monitor Reports之类的工具监视并行SQL语句,以确保服务器实际上正在使用所请求的并行性。)