2017-08-30 58 views
0

我有它运行约4-6分钟,这个PL/SQL程序:如何使PL/SQL执行得更快

DECLARE 
    i NUMBER := 0; 
    begin 
    for x in (select  anumber 
       ,   position 
       ,   character 
       from  sdc_positions_cip 
       where  kind = 'Name') 
loop  
    update sdc_compare_person dcip 
    set dcip.GESNAM_D = substr(dcip.GESNAM_D, 1, x.position - 1) || x.character || 
    substr(dcip.GESNAM_D, x.position + 1, length(dcip.GESNAM_D) - x.position) 
    where dcip.sourcekey = x.anumber; 

    i := i + 1; 
    IF i > 100 THEN COMMIT; 
    i := 0; 
    END IF; 
end loop; 
commit; 
end; 
/

心中已经放在dcip.sourcekeyx.anumber的索引。 它使用的表空间是10GB。

有没有办法让这个程序(很多)更快?

+0

多久查询持续多久?我没有看到有太多的改善,你也可以添加索引“kind”。如果数据量为10GB,那么表格中有很多数据。 – MirzaS

+5

摆脱频繁的提交。最后只提交一次。 –

回答

10

您的性能瓶颈是循环。它强制你的代码在每一个UPDATE-语句之间在PLSQL和Oracle SQL之间切换。

为了消除这些上下文切换,你很可能使用含有子查询的UPDATE语句来,但我更喜欢MERGE,例如像以下列方式:

merge into sdc_compare_person dcip 
using (
    select anumber, position, character 
    from sdc_positions_cip 
    where kind = 'Name' 
) x 
on (dcip.sourcekey = x.anumber) 
when matched then update set 
    dcip.GESNAM_D = substr(dcip.GESNAM_D, 1, x.position - 1) || 
    x.character || 
    substr(dcip.GESNAM_D, x.position + 1, length(dcip.GESNAM_D) - x.position); 

另一种选择是将使用BULK COLLECT INTOFORALL执行批量选择和批量插入。由于程序复杂性有限,我强烈建议使用像我这样的单个语句。

+0

非常好!而不是5分钟,查询只需要3秒!谢谢@Thomas Tschernich – Erwin

0

你也可以试试这个版本:

update 
    (select dcip.GESNAM_D, x.position, x.character, dcip.sourcekey, anumber 
    from sdc_compare_person dcip 
     join sdc_positions_cip on dcip.sourcekey = x.anumber) 
set GESNAM_D = substr(GESNAM_D, 1, position - 1) || character || substr(GESNAM_D, position + 1, length(GESNAM_D) - position);