FETCH BULK COLLECT 不在包中 return

FETCH BULK COLLECT not return in package

这是我的问题,当我执行一个包来归档一些数据时,它在命令

上阻塞
FETCH cAPP_T_TMP BULK COLLECT
INTO t_app_t
limit nLIMIT;

但是当在 SQL 的程序中使用相同的命令时,开发人员此操作需要 16 秒 运行。

包中的 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 的 16 秒内运行的代码 开发者:

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

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

似乎该包是由另一个用户执行的,该用户已被 DBA 优化为 OLTP。该过程试图获取拥有数百万条记录的 table。因此,当我使用我的用户执行它时,它的效果会更好。