INSERT INTO的速度

时间:2016-03-10 18:50:58

标签: sql oracle plsql insert procedure

我有一个工作程序,我用来将记录从一个表移动到另一个表:

create or replace procedure p_insert_sdpcenroll
  as 

  v_rec_cnt number := 0;

  cursor c_de_data is
    select a.term
      ,a.report_date
      ,a.report_type
      ,a.metric_num
      ,a.metric
      ,a.total
 from sdpcenroll_stg a;

 type de_table is table of c_de_data%rowtype index by binary_integer;
 t_de_table de_table;

begin

open c_de_data;

loop

  fetch c_de_data bulk collect
    into t_de_table limit 100;

  exit when t_de_table.count = 0;  

    forall de_rec in 1..t_de_table.count
      --insert into sdpcenroll (term, report_date, report_type, metric_num, metric, total)
      insert into (select a.term
                         ,a.report_date
                         ,a.report_type
                         ,a.metric_num
                         ,a.metric
                         ,a.total
                   from sdpcenroll a)
        values (t_de_table(de_rec).term
               ,t_de_table(de_rec).report_date
               ,t_de_table(de_rec).report_type
               ,t_de_table(de_rec).metric_num
               ,decode(t_de_table(de_rec).metric_num, '9', 'TS_GPC_Total (unduplicated)', t_de_table(de_rec).metric)
               ,t_de_table(de_rec).total)
          log errors into err$_sdpcenroll reject limit unlimited;

      v_rec_cnt := v_rec_cnt + sql%rowcount;

end loop;

close c_de_data;

dbms_output.put_line(v_rec_cnt||' total rows inserted.');  

delete from sdpcenroll_stg;
dbms_output.put_line(sql%rowcount||' staging rows deleted.');

exception
  when others then
    raise_application_error(-20100, 'Processing error occurred. Check log table for error records. '||sqlcode||' - '||sqlerrm);                 

end p_insert_sdpcenroll;

对于大约500K记录,该过程在大约27秒内运行。但是,如果我使用注释掉的INSERT INTO代码替换INSERT INTO代码,则该过程将持续减慢到大约34秒。

INSERT INTO table (columns)本身是否比INSERT INTO (SELECT columns FROM table)慢,或者这只是在这个特定程序中弹出的怪癖?

1 个答案:

答案 0 :(得分:2)

我不知道通过匿名视图插入本身是否比INSERT...(column list)...更快。

但是,考虑到您已经显示的代码,没有必要将数据读入内存然后将其写回。相反,您可以使用INSERT...SELECT...构造,如

create or replace procedure p_insert_sdpcenroll   as 
BEGIN
  INSERT INTO (SELECT TERM,
                      REPORT_DATE,
                      REPORT_TYPE,
                      METRIC_NUM,
                      METRIC,
                      TOTAL
                 FROM SDPCENROLL)
  SELECT TERM
         REPORT_DATE
         REPORT_TYPE
         METRIC_NUM
         DECODE(METRIC_NUM,
                  '9', 'TS_GPC_Total (unduplicated)', 
                       METRIC),
         TOTAL
    FROM SDPCENROLL_STG
    log errors into err$_sdpcenroll
    reject limit unlimited;

  dbms_output.put_line(SQL%ROWCOUNT||' total rows inserted.');  

  delete from sdpcenroll_stg;
  dbms_output.put_line(sql%rowcount||' staging rows deleted.');
exception
  when others then
    raise_application_error(-20100, 'Processing error occurred. Check log table for error records. '||sqlcode||' - '||sqlerrm);                 
end p_insert_sdpcenroll;

祝你好运。