2017-08-30 40 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);