plsql过程的优化,包括基于循环的插入在包括clob列的表上

问题描述 投票:0回答:1

请帮助我调整以下类型的程序代码。基本前提是我需要选择数据并插入表中。我可以直接在select中插入,但每行都需要clob列计算。

以下是表格和代码。

    create table test_clob_performance
(col1 number , col2 number , col3 number , col4 number , col5 number , col6 number , col7 number , col8 number 
, clob1 clob , clob2 clob , clob3 clob , clob4 clob) ;



-- This is just a test function actual function derives ddata from tables on the basis of the input parameters
create or replace function some_func_for_clob(val number)
return clob
is 
begin
return rpad('test clob' , val , '*');
exception when others then 
raise_application_error(-20001 , sqlerrm||dbms_utility.format_error_stack);
end;




create or replace 
PROCEDURE insert_clob_performance IS

   CURSOR c1  IS
   SELECT  rownum  as col1, rownum+1 col2, rownum+1 col3, rownum+4 col4, rownum+5 col5,rownum+6 col6, rownum+7 col7
   , rownum+8  col8 from dual connect by rownum < 10000 ;

      var_clob1            CLOB;
      var_clob2           CLOB;
      var_clob3          CLOB;
      var_clob4           CLOB;

 BEGIN


   FOR z IN c1   LOOP

     var_clob1 := some_func_for_clob(z.col1 );
     var_clob2 := some_func_for_clob(z.col1 );
     var_clob3 := some_func_for_clob(z.col1 );
     var_clob4 := some_func_for_clob(z.col1 );

  INSERT /*+ APPEND */ INTO test_clob_performance (col1 , col2 , col3 , col4 , col5 ,col6 , col7 , col8,clob1 , clob2 , clob3 , clob4)
  values (z.col1 , z.col2 , z.col3 , z.col4 , z.col5 ,z.col6 , z.col7 , z.col8,var_clob1 , var_clob2 , var_clob3 , var_clob4);


    END LOOP;
  END ;

 /

例如,执行insert_clob_performance需要17秒才能在12.2 Oracle数据库中完成。当我尝试使用批量收集来改善这一点时,性能会变差,insert_clob_performance_opt需要23秒才能完成。即使我将限制条款更改为仅100,性能与原始代码类似。

请建议在这里可以做些什么来改善性能。

create or replace 
PROCEDURE insert_clob_performance_opt IS

   CURSOR c1  IS
   SELECT  rownum  as col1, rownum+1 col2, rownum+1 col3, rownum+4 col4, rownum+5 col5,rownum+6 col6, rownum+7 col7
   , rownum+8  col8 , '', '' , '' , '' from dual connect by rownum < 10000 ;

      var_clob1            CLOB;
      var_clob2           CLOB;
      var_clob3          CLOB;
      var_clob4           CLOB;

      type clob_perf_rec is table of test_clob_performance%rowtype ;
      clob_perf_tab clob_perf_rec;

 BEGIN

open c1 ;

  LOOP

  FETCH c1 bulk collect into clob_perf_tab LIMIT 1000;

  exit when clob_perf_tab.count = 0 ;

  for i in clob_perf_tab.first .. clob_perf_tab.last loop
    clob_perf_tab(i).clob1 := some_func_for_clob(clob_perf_tab(i).col1 );
    clob_perf_tab(i).clob2 := some_func_for_clob(clob_perf_tab(i).col2 );
    clob_perf_tab(i).clob3 := some_func_for_clob(clob_perf_tab(i).col3 );
    clob_perf_tab(i).clob4 := some_func_for_clob(clob_perf_tab(i).col4 );
  end loop;

  forall i in clob_perf_tab.first .. clob_perf_tab.last
    INSERT /*+ APPEND */ INTO test_clob_performance (col1 , col2 , col3 , col4 , col5 ,col6 , col7 , col8,clob1 , clob2 , clob3 , clob4)
    values (clob_perf_tab(i).col1 , clob_perf_tab(i).col2 , clob_perf_tab(i).col3 , clob_perf_tab(i).col4 , 
    clob_perf_tab(i).col5 ,clob_perf_tab(i).col6 , clob_perf_tab(i).col7 , clob_perf_tab(i).col8,
    clob_perf_tab(i).clob1 , clob_perf_tab(i).clob2 , clob_perf_tab(i).clob3 , clob_perf_tab(i).clob4);


    END LOOP;
  END ;
oracle performance plsql bulkinsert clob
1个回答
0
投票

尝试使用单个insert-from-select语句执行此操作:

INSERT INTO test_clob_performance (col1 , col2 , col3 , col4 , col5 ,col6 , col7 , col8,clob1 , clob2 , clob3 , clob4)
SELECT col1 , col2 , col3 , col4 , col5 ,col6 , col7 , col8, some_func_for_clob(col1), some_func_for_clob(col2), some_func_for_clob(col3), some_func_for_clob(col4) 
FROM
(SELECT  rownum  as col1, rownum+1 col2, rownum+1 col3, rownum+4 col4, rownum+5 col5,rownum+6 col6, rownum+7 col7, rownum+8 col8 from dual connect by rownum < 10000) ;
© www.soinside.com 2019 - 2024. All rights reserved.