繁体   English   中英

PLSQL性能问题

[英]PLSQL Performance Issue

这更多的是怀疑而不是问题。 我只需要从一个表中选择一些通用字段,然后将其插入到另一个表中。 我用2种不同的样式完成了代码,但都使用BULK COLLECT。 哪个是更好的选择,或者除此之外还有其他方法吗?

请在下面找到必要的详细信息。

程序(方法1):

  create or replace procedure a2 is
     cursor c1 is select id,address from emp1;
     type t is table of c1%rowtype;
     c t;
  begin
     open c1;
     loop
        fetch c1 bulk collect into c;
        exit when c.count=0;
        forall j in 1..c.count save exceptions
        insert into empl1(id,address) values (c(j).id,c(j).address);
     end loop;
     commit;
  exception when others then
     for j in 1..sql%bulk_exceptions.count loop
        dbms_output.put_line('The sql error is error occured');
     end loop;
  end a2;
  / 

运行以上过程并输出:

declare
a number;
begin
dbms_output.put_line ('before procedure: ' || to_char(sysdate, 'HH24:MI:SS'));
a2;
dbms_output.put_line ('after procedure: ' || to_char(sysdate, 'HH24:MI:SS'));
end;

输出:

 before procedure: 23:44:48
 after procedure: 23:45:47
 PL/SQL procedure successfully completed.

因此,以上过程花费了59秒来插入34801020记录。

现在,请找到第二个步骤。

程序(方法2):

create or replace procedure a3 is
   cursor c1 is select id,address from emp1;
   type t is table of c1%rowtype;
   c t;
begin
   select id,address  bulk collect into c from emp1;
   forall j in 1..c.count save exceptions
   insert into empl1(id,address) values (c(j).id,c(j).address);
exception when others then
   for j in 1..sql%bulk_exceptions.count loop
      dbms_output.put_line('The sql error is error occured');
   end loop;
end a3;
 / 

使用output运行上述过程。

declare
a number;
begin
dbms_output.put_line ('before procedure: ' || to_char(sysdate, 'HH24:MI:SS'));
a3;
dbms_output.put_line ('after procedure: ' || to_char(sysdate, 'HH24:MI:SS'));
end;

输出:

before procedure: 23:47:57
after procedure: 23:48:53
PL/SQL procedure successfully completed.

该过程花费了56秒来插入34801020记录。

emp1表中的总记录。

 SQL> select count(1) from emp1;

   COUNT(1)
   ----------
   34801020

因此,我的问题是:

以上两种方法中的哪一种是将3百万条记录插入表中的最佳方法,如果有其他更好的方法可以完成上述插入过程,请告诉我。

我使用具有相似数据集大小的相似代码运行了测试

使用游标循环

  create or replace procedure a2 is
     cursor c1 is select empno,ename from bigemp;
     type t is table of c1%rowtype;
     c t;
  begin
     open c1;
     loop
        fetch c1 bulk collect into c;
        exit when c.count=0;
        forall j in 1..c.count save exceptions
        insert into bigemp2(empno,ename) values (c(j).empno,c(j).ename);
     end loop;
     commit;
  exception when others then
     for j in 1..sql%bulk_exceptions.count loop
        dbms_output.put_line('The sql error is error occured');
     end loop;
  end a2;


SQL> exec a2

PL/SQL procedure successfully completed.

Elapsed: 00:00:56.93

执行常规的插入语句,而不使用cursor-for循环

SQL> insert into bigemp2( empno, ename )
select  empno, ename from bigemp t2


29360128 rows created.

Elapsed: 00:00:11.30

现在执行直接路径插入

SQL> insert /*+ append */ into bigemp2( empno, ename )
select empno, ename from bigemp t2
;


29360128 rows created.

Elapsed: 00:00:06.01

添加一些并行性

SQL> alter session enable parallel dml;

Session altered

SQL> insert /*+ append parallel(2 ) */ into bigemp2( empno, ename )
select /* parallel( t2, 2 ) */ empno, ename from bigemp t2
;

29360128 rows created.

Elapsed: 00:00:03.52

因此,总而言之,仅通过使用适当的技术,我们就可以使处理过程和数量级加快(快大约16倍)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM