百万行的BULK COLLECT问题 - 进程内存不足

时间:2017-01-19 20:33:07

标签: oracle plsql

我的pl / sql程序中有以下代码,它试图收集1700万行,并且在尝试分配16328字节时失败并出现错误ORA-04030:进程内存(koh-kghu调用,pmuccst:风干吨/记录)

    TYPE rc_test IS RECORD(
  ROWID VARCHAR2(200), 
  contact_id VARCHAR2(200),
  last_name VARCHAR2(200), 
  first_name VARCHAR2(200), 
  phone VARCHAR2(200), 
  email VARCHAR2(200), 
  birth_day date,
  address_id VARCHAR2(200),  
  seq NUMBER,
  NEWID NUMBER); 

TYPE rctype 
  IS TABLE OF RC_TEST; 

rcrecords RCTYPE; 

BEGIN

SELECT ROWID, 
       contact_id,
       last_name, 
       first_name, 
       phone, 
       email, 
       birth_day,
       address_id,
       seq,
       NEWID
bulk   collect INTO rcrecords 
FROM   HR.TMP_TBL_SEQ a
order by last_name, first_name, seq;

FOR i IN 1..rcrecords.count LOOP 

- <<>> END LOOP;

它可以运行数百或数千行的样本数据,但不能用于数百万行。

我已阅读此错误的故障排除但其中大多数都是围绕通过DBA完成此操作,DBA将执行某些调整或建议我们增加可能解决问题的RAM但由于首先我确实想要的某些限制改变代码本身的逻辑。

有没有更好的方法来改善上述类型代码中的逻辑以摆脱内存不足错误?

代替我的代码中使用的表记录,任何人都可以提供替代代码吗?

非常感谢。

3 个答案:

答案 0 :(得分:0)

您可以将BULK COLLECTLIMIT子句(http://www.oracle.com/technetwork/issue-archive/2008/08-mar/o28plsql-095155.html)一起使用。在您的情况下,它看起来类似于:

CURSOR  cur1 IS 
  SELECT ROWID, contact_id, last_name, first_name, 
  phone, email, birth_day, address_id, seq, 
  NEWID FROM HR.TMP_TBL_SEQ a order by last_name, first_name, seq;
TYPE T_TEST  IS TABLE OF cur1 %ROWTYPE  INDEX BY PLS_INTEGER;;
test_data T_TEST;
BEGIN   
OPEN cur1;
LOOP
    FETCH cur1
        BULK COLLECT INTO test_data LIMIT 10000;

    FOR indx IN 1 .. test_data.COUNT 
    LOOP
        NULL;
        --- process data
    END LOOP;

    EXIT WHEN test_data.COUNT < 10000;
 END LOOP;
 CLOSE cur1;

答案 1 :(得分:0)

使用LIMIT子句避免对BULK COLLECT进行这种“无限制”使用。 将SELECT语句移动到显式游标声明中,然后使用简单循环从表中获取许多但不是所有行,每次执行循环体时都使用可选的LIMIT子句。

有关示例和解释,请参阅此oracle技术问题,请参阅http://www.oracle.com/technetwork/issue-archive/2008/08-mar/o28plsql-095155.html

答案 2 :(得分:0)

用游标for-loop替换BULK COLLECT

begin
    for rcrecords in
    (
        SELECT ROWID, 
               contact_id,
               last_name, 
               first_name, 
               phone, 
               email, 
               birth_day,
               address_id,
               seq,
               NEWID
        bulk   collect INTO rcrecords 
        FROM   HR.TMP_TBL_SEQ a
        order by last_name, first_name, seq
    ) loop
        --Process data.
        null;
    end loop;
end;
/

Oracle将自动负责批量收集,限制和声明数据类型。