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。因此,当我使用我的用户执行它时,它的效果会更好。
这是我的问题,当我执行一个包来归档一些数据时,它在命令
上阻塞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。因此,当我使用我的用户执行它时,它的效果会更好。