Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用批量收集提高plsql的性能_Sql_Oracle_Plsql - Fatal编程技术网

使用批量收集提高plsql的性能

使用批量收集提高plsql的性能,sql,oracle,plsql,Sql,Oracle,Plsql,我使用批量收集来提高执行时间。当我不使用批量收集时,它会在4分钟内执行。 但当我使用批量收集时,并没有输出,控制台中也不会显示错误消息。我可以看到创建了一个空白的spool文件。 请让我知道,如果我使用批量收集不正确,我们也可以在select语句中使用此子句并限制吗? 表由最多100万条记录组成 SET SERVEROUTPUT ON FORMAT WRAPPED SET VERIFY OFF SET FEEDBACK OFF SET TERMOUT OFF SPOOL C:\Temp\spo

我使用批量收集来提高执行时间。当我不使用批量收集时,它会在4分钟内执行。 但当我使用批量收集时,并没有输出,控制台中也不会显示错误消息。我可以看到创建了一个空白的spool文件。 请让我知道,如果我使用批量收集不正确,我们也可以在select语句中使用此子句并限制吗? 表由最多100万条记录组成

SET SERVEROUTPUT ON FORMAT WRAPPED
SET VERIFY OFF
SET FEEDBACK OFF
SET TERMOUT OFF

SPOOL C:\Temp\spool_1.txt

DECLARE

  cursor c2 is (
    select count(distinct e.cdb_pref_event_id)
          ,e.supp_cd
      from (select distinct eh.cdb_customer_id   cdb_customer_id
                           ,eh.cdb_pref_event_id cdb_pref_event_id
                           ,eh.supp_cd           supp_cd
              from (select *
                      from cdb_stg.cpm_pref_event_stg_arc
                     where trunc(load_date) = trunc(sysdate - 1)) eh
              Left outer join cdb_admin.cpm_pref_result er on (eh.cdb_customer_id =
                                                              er.cdb_customer_id and
                                                              eh.cdb_pref_event_id =
                                                              er.cdb_pref_event_id)
             where er.cdb_pref_event_id is null
               and er.cdb_customer_id is null) r
      join cdb_admin.cpm_pref_event_exception e on (r.cdb_customer_id =
                                                   e.cdb_customer_id and
                                                   r.cdb_pref_event_id =
                                                   e.cdb_pref_event_id)
     group by e.supp_cd);

  TYPE totalprefresults is table of NUMBER(20);
  TYPE supcd_1 is table of cdb_admin.cpm_pref_event_stg.supp_cd%TYPE;
  total_prefresults totalprefresults;
  supcd1            supcd_1;
  --Total_prefresults NUMBER(20);
  --SUPCD1 CDB_ADMIN.CPM_PREF_EVENT_STG.supp_cd%TYPE;
  profile_counts NUMBER(20);

  iter Integer := 0;

BEGIN

  select count(distinct cdb_customer_id)
    into profile_counts
    from cdb_admin.cpm_pref_event_exception h
   where cdb_customer_id in
         (Select distinct e.cdb_customer_id
            from (Select distinct eh.cdb_customer_id   cdb_customer_id
                                 ,eh.cdb_pref_event_id cdb_pref_event_id
                                 ,eh.supp_cd           supp_cd
                    from (select *
                            from cdb_stg.cpm_pref_event_stg_arc
                           where trunc(load_date) = trunc(sysdate - 1)) eh
                    Left outer join cdb_admin.cpm_pref_result er on (eh.cdb_customer_id =
                                                                    er.cdb_customer_id and
                                                                    eh.cdb_pref_event_id =
                                                                    er.cdb_pref_event_id)
                   where er.cdb_pref_event_id is null
                     and er.cdb_customer_id is null) r
            join cdb_admin.cpm_pref_event_exception e on (r.cdb_customer_id =
                                                         e.cdb_customer_id and
                                                         r.cdb_pref_event_id =
                                                         e.cdb_pref_event_id)
           where e.supp_cd = 'PROFILE-NOT-FOUND')
     and h.supp_cd != 'PROFILE-NOT-FOUND';

  dbms_output.put_line('TOTAL EVENTS VALIDATION');
  dbms_output.put_line('-------------------------------------------------------------');
  dbms_output.put_line('');

  dbms_output.put_line(rpad('Pref_Counts', 25) || rpad('Supp_CD', 25));

  OPEN c2;
  LOOP
    FETCH c2 BULK COLLECT
      INTO total_prefresults
          ,supcd1 limit 100;
    EXIT WHEN c2%NOTFOUND;
    dbms_output.put_line(rpad(total_prefresults, 25) || rpad(supcd1, 25));

    IF (supcd1 = 'PROFILE-NOT-FOUND')
    then
      dbms_output.put_line('');
      dbms_output.put_line('Profile not found records count : ' ||
                           total_prefresults);

      dbms_output.put_line(profile_counts ||
                           ' : counts moved to other exceptions ');
      dbms_output.put_line((total_prefresults - profile_counts) ||
                           ' : are still in Profile_not_found exception');

    END IF;

    iter := iter + 1;
  END LOOP;
  CLOSE c2;
  dbms_output.put_line('');
  dbms_output.put_line('Number of missing Records: ' || iter);

END;
/
SPOOL OFF

我已经从
openc2开始重新编写了您的代码至<代码>关闭c2

应执行
批量收集
以仅存储收集中的所有数据一次(一次性),然后可使用
FOR loop
中的索引(即在以下情况下为i)使用此收集,如下所示:

OPEN C2; 
FETCH C2 BULK COLLECT INTO
    TOTAL_PREFRESULTS,
    SUPCD1;
--EXIT WHEN C2%NOTFOUND;
CLOSE C2;

-- To list down all the values before processing the logic
FOR I IN TOTAL_PREFRESULTS.FIRST..TOTAL_PREFRESULTS.LAST LOOP
DBMS_OUTPUT.PUT_LINE(RPAD(TOTAL_PREFRESULTS(I), 25)
                     || RPAD(SUPCD1(I), 25));
END LOOP;


FOR I IN TOTAL_PREFRESULTS.FIRST..TOTAL_PREFRESULTS.LAST LOOP
    IF ( SUPCD1(I) = 'PROFILE-NOT-FOUND' ) THEN
        DBMS_OUTPUT.PUT_LINE('');
        DBMS_OUTPUT.PUT_LINE('Profile not found records count : ' || TOTAL_PREFRESULTS(I));
        DBMS_OUTPUT.PUT_LINE(PROFILE_COUNTS || ' : counts moved to other exceptions ');
        DBMS_OUTPUT.PUT_LINE((TOTAL_PREFRESULTS(I) - PROFILE_COUNTS)
                             || ' : are still in Profile_not_found exception');
    END IF;

    ITER := ITER + 1;
END LOOP;
在代码中替换上述代码段并尝试执行

参考


干杯

我已经从
打开c2开始重新编写了您的代码至<代码>关闭c2

应执行
批量收集
以仅存储收集中的所有数据一次(一次性),然后可使用
FOR loop
中的索引(即在以下情况下为i)使用此收集,如下所示:

OPEN C2; 
FETCH C2 BULK COLLECT INTO
    TOTAL_PREFRESULTS,
    SUPCD1;
--EXIT WHEN C2%NOTFOUND;
CLOSE C2;

-- To list down all the values before processing the logic
FOR I IN TOTAL_PREFRESULTS.FIRST..TOTAL_PREFRESULTS.LAST LOOP
DBMS_OUTPUT.PUT_LINE(RPAD(TOTAL_PREFRESULTS(I), 25)
                     || RPAD(SUPCD1(I), 25));
END LOOP;


FOR I IN TOTAL_PREFRESULTS.FIRST..TOTAL_PREFRESULTS.LAST LOOP
    IF ( SUPCD1(I) = 'PROFILE-NOT-FOUND' ) THEN
        DBMS_OUTPUT.PUT_LINE('');
        DBMS_OUTPUT.PUT_LINE('Profile not found records count : ' || TOTAL_PREFRESULTS(I));
        DBMS_OUTPUT.PUT_LINE(PROFILE_COUNTS || ' : counts moved to other exceptions ');
        DBMS_OUTPUT.PUT_LINE((TOTAL_PREFRESULTS(I) - PROFILE_COUNTS)
                             || ' : are still in Profile_not_found exception');
    END IF;

    ITER := ITER + 1;
END LOOP;
在代码中替换上述代码段并尝试执行

参考


干杯

我认为瓶颈是这样的条件:
其中trunc(load_date)=trunc(sysdate-1)

您在
trunc(加载日期)
上有索引吗?根据
trunc(load\u date)
创建基于函数的索引,或者如果您已经在
load\u date
上创建了索引,请重试

WHERE load_date >= trunc(sysdate - 1) AND load_date < trunc(sysdate)
其中加载日期>=trunc(sysdate-1)和加载日期

还要检查您的查询是否真的需要
distinct
。如果可能,请删除它们。

我认为瓶颈是这样的情况:
其中trunc(加载日期)=trunc(sysdate-1)

您在
trunc(加载日期)
上有索引吗?根据
trunc(load\u date)
创建基于函数的索引,或者如果您已经在
load\u date
上创建了索引,请重试

WHERE load_date >= trunc(sysdate - 1) AND load_date < trunc(sysdate)
其中加载日期>=trunc(sysdate-1)和加载日期

还要检查您的查询是否真的需要
distinct
。如果可能,请删除它们。

批量收集可以提供可观的性能增益。然而,其中也有一些问题
首先,%notfound的含义不同。 在标准游标上%notfound表示所有行都已提取,没有其他行。对于批量收集,此更改为“没有足够的行达到指定的限制(如果存在)”。 这并不意味着没有获取行,只是没有达到指定的限制。例如,如果您的限制为100,并且仅检索到50次提取,则%notfound将返回True。这就是参考指南失败的地方。
第二个是没有limit子句的情况:游标中的所有行都返回到共享内存(PGA?)中。那有什么问题呢。 如果有100行或1000行,则很可能是k,但假设有100000行或1M行,它们仍然全部加载到内存中。最后(至少现在)当使用limit子句时,整个Fetch+进程本身必须包含在一个循环中,或者您只处理第一次Fetch,即只处理指定的限制行数,而不管实际存在多少行。参考指南失败的另一点。 以下骨架适用于上述情况

    declare 
       max_bulk_rows constant integer  := 1000;  -- define the max number of rows for each fetch ... 

       cursor c_bulk is(
        Select ... ;

       type bulk_row_t is table of c_bulk%rowtype; 
       bulk_row  bulk_row_t; 

    Begin 
       open c_bulk;  
       loop
           fetch c_bulk                      -- fill buffer 
           bulk collect into  bulk_row
           limit max_bulk_row; 

           for i in bulk_row.first .. bulk_row.last -- process each row in buffer 
           loop
               "process individual row here"
           end loop; 

           foreach ...                      -- bulk output of rows here is needed.

           exit when bulk_row.count < max_bulk_row;  -- exit process loop if all rows processed

       end loop ;   -- loop back and fetch next buffer if needed
   close c_bulk;
    ...
   end; 
声明
最大批量行常量整数:=1000;--定义每次提取的最大行数。。。
游标c_批量为(
选择;
类型bulk\u row\t是c\u bulk%rowtype的表;
大排大排;
开始
开放式散装;
环
获取c_批量--填充缓冲区
批量收集到批量_行
限制最大批量行;
对于bulk\u row.first..bulk\u row.last中的i——处理缓冲区中的每一行
环
“在此处处理单个行”
端环;
foreach…--这里需要大量输出行。
当bulk_row.count
批量收集可以提供可观的性能提升。但是,其中涉及到一些问题。
首先,%notfound的含义不同。 在标准游标上%notfound表示已提取所有行,并且没有其他行。对于批量收集,此更改为“没有足够的行达到指定的限制(如果存在)”。 这并不意味着没有获取任何行,只是未达到指定的限制。例如,如果限制为100,并且仅检索到50,则%notfound将返回True。这就是引用的指南失败的原因。
第二个问题是在没有limit子句的情况下会发生什么:游标中的所有行都返回到共享内存(PGA?)中。那么这有什么问题呢。 如果有100行或1000行,那么很可能是k,但假设有100000行或1M行,它们仍然全部加载到内存中当使用limit子句时,整个Fetch+进程本身必须包含在一个循环中,或者您只处理第一次Fetch(仅表示指定的限制行数),而不管实际存在多少行。参考指南失败的另一点。 以下骨架适用于上述情况

    declare 
       max_bulk_rows constant integer  := 1000;  -- define the max number of rows for each fetch ... 

       cursor c_bulk is(
        Select ... ;

       type bulk_row_t is table of c_bulk%rowtype; 
       bulk_row  bulk_row_t; 

    Begin 
       open c_bulk;  
       loop
           fetch c_bulk                      -- fill buffer 
           bulk collect into  bulk_row
           limit max_bulk_row; 

           for i in bulk_row.first .. bulk_row.last -- process each row in buffer 
           loop
               "process individual row here"
           end loop; 

           foreach ...                      -- bulk output of rows here is needed.

           exit when bulk_row.count < max_bulk_row;  -- exit process loop if all rows processed

       end loop ;   -- loop back and fetch next buffer if needed
   close c_bulk;
    ...
   end; 
声明
max_bulk_rows常量整数:=1000;--定义每次提取的最大行数。。。
游标c_批量为(
选择;
类型bulk\u row\t是c\u bulk%rowtype的表;
大排大排;
开始
开放式散装;
环
取c_块