FETCH BULK COLLECT不会退回包裹

时间:2015-08-03 15:41:41

标签: plsql oracle11g cursor fetch

这是我的问题,当我执行一个包来存档它在命令

上阻止的一些数据时
FETCH cAPP_T_TMP BULK COLLECT
INTO t_app_t
limit nLIMIT;

但是当SQL Developper中的一个过程中的相同命令执行此操作时,需要运行16个secondes。

nLimit在包装中的误差为50 000。

简而言之,我在程序包中有一个其他程序可以使用相同的归档策略。唯一的区别是游标有不同的select语句。

这是我在pacakge中的代码:

procedure APP_TRX (p_date in varchar2, p_tableName out varchar2, p_timeRequired out varchar2, p_nbLinesTransfered out varchar2) is

  cursor cAPP_T_TMP is
    SELECT
    APP.ID_APP,
    APP.ID_T,
    APP.ID_EVENT_CREA,
    APP.DT_CREA,
    APP.ID_EVENT_ANNUL,
    APP.DT_ANNUL,
    APP.ID_MAI,
    APP.ID_F,
    APP.M_APP,
    APP.C_APP,
    APP.T_C,
    max(ATB.DT_EPUR) AS DT_EPUR
    FROM APP_T APP
    JOIN ARCH_T_BODY ATB ON APP.ID_TRX = ATB.ID_TRX_TRANSACTION
    WHERE NOT EXISTS (SELECT TP.ID_TRX FROM T_PAP TP WHERE TP.ID_TRX = APP.ID_TRX)
    AND NOT EXISTS (SELECT TI.ID_TRX FROM T_INST TI WHERE TI.ID_TRX = APP.ID_TRX)
    AND NOT EXISTS (SELECT TP.ID_TRX FROM T_P TP WHERE TP.ID_TRX = APP.ID_TRX)
    AND NOT EXISTS (SELECT TCD.ID_TRX FROM T_CRE TCD WHERE TCD.ID_TRX = APP.ID_TRX)
    AND NOT EXISTS (SELECT MB.ID_TRX FROM M_BAN MB WHERE MB.ID_TRX = APP.ID_TRX)
    GROUP BY APP.ID_APP,APP.ID_T,APP.ID_EVENT_CREA,APP.DT_CREA,APP.ID_EVENT_ANNUL,
    APP.DT_ANNUL,APP.ID_MAI,APP.ID_F,APP.M_APP,APP.C_APP,APP.T_C;

  type type_app_t is TABLE OF cAPP_T_TMP %ROWTYPE INDEX BY PLS_INTEGER;
  t_app_t type_app_t ;

  nLOT pls_integer := 1;
  nbDeleted int :=0;
  nbTransfered int :=0;
  nbTransferedTemp int :=0; nbAlreadyIn int :=0;

begin 
  trc.trc_on('ARCHIVE_APP_T');
  p_tableName := 'APP_T(B)';
  allBEGIN_TIMESTAMP := systimestamp;
  open cAPP_T_TMP ;  
  loop
    lotBEGIN_TIMESTAMP := systimestamp;
    dbms_application_info.set_module('before fetch',trim(to_char(nLOT * nLIMIT,'999G999G999')));

    FETCH cAPP_T_TMP BULK COLLECT  <-- here the command who block
    INTO t_app_t
      limit nLIMIT;

    dbms_application_info.set_module('AFTER FETCH',trim(to_char(nLOT * nLIMIT,'999G999G999')));
    exit when t_app_t.count = 0;
    ...

这是在Sql Developer中16个secondes中运行的代码:

declare
cursor cAPP_T_TMP is
    SELECT
    APP.ID_APP,
    APP.ID_T,
    APP.ID_EVENT_CREA,
    APP.DT_CREA,
    APP.ID_EVENT_ANNUL,
    APP.DT_ANNUL,
    APP.ID_MAI,
    APP.ID_F,
    APP.M_APP,
    APP.C_APP,
    APP.T_C,
    max(ATB.DT_EPUR) AS DT_EPUR
    FROM APP_T APP
    JOIN ARCH_T_BODY ATB ON APP.ID_TRX = ATB.ID_TRX_TRANSACTION
    WHERE NOT EXISTS (SELECT TP.ID_TRX FROM T_PAP TP WHERE TP.ID_TRX = APP.ID_TRX)
    AND NOT EXISTS (SELECT TI.ID_TRX FROM T_INST TI WHERE TI.ID_TRX = APP.ID_TRX)
    AND NOT EXISTS (SELECT TP.ID_TRX FROM T_P TP WHERE TP.ID_TRX = APP.ID_TRX)
    AND NOT EXISTS (SELECT TCD.ID_TRX FROM T_CRE TCD WHERE TCD.ID_TRX = APP.ID_TRX)
    AND NOT EXISTS (SELECT MB.ID_TRX FROM M_BAN MB WHERE MB.ID_TRX = APP.ID_TRX)
    GROUP BY APP.ID_APP,APP.ID_T,APP.ID_EVENT_CREA,APP.DT_CREA,APP.ID_EVENT_ANNUL,
    APP.DT_ANNUL,APP.ID_MAI,APP.ID_F,APP.M_APP,APP.C_APP,APP.T_C;

  type type_app_t is TABLE OF cAPP_T_TMP %ROWTYPE INDEX BY PLS_INTEGER;
  t_app_t type_app_t ;
  compt int := 0;
  nLIMIT pls_integer := 50000; 
begin 
 DBMS_OUTPUT.put_line('before open ' || systimestamp);
  open cAPP_T_TMP ;
  loop
    compt := compt +1;
    DBMS_OUTPUT.put_line('before fetch ' || systimestamp);

    FETCH cAPP_T_TMP BULK COLLECT
    INTO t_app_t
      limit nLIMIT;

    DBMS_OUTPUT.put_line('after fetch ' || systimestamp);
    exit when t_app_t.count = 0;
    end loop;
  close cAPP_T_TMP ; 
  DBMS_OUTPUT.put_line('after close ' || systimestamp || 'compt = ' || compt);

end;

正如你可以看到它的相同代码,但是由于我不知道它只是在包内部不起作用的原因。

我已经在包内部验证了我的其他程序,代码是相同的。

提前致谢。

编辑#1

我试图将程序提取到一个匿名块中,它就像一个魅力。所以我做了另一个测试,我试着直接调用我的包中的程序,但仍然遇到问题。最后,我尝试将我的anonyme块中的代码直接复制到包内,但同样的问题也出现了。为什么在我的包中,当数据在包外非常快时,我无法存档数据。

1 个答案:

答案 0 :(得分:0)

似乎是由DBA针对OLTP优化的另一个用户执行了包。而且这个过程试图获取拥有数百万条记录的表格。因此,当我使用我的用户执行它时,它的工作方式会更好。