嵌套的Cursor导致性能问题

时间:2017-10-30 19:39:23

标签: oracle performance plsql nested cursor

有两个表

PARENT_OBJECT
  PARENT_ID
  ATTR1
  ...
  ATTRn


CHILD_OBJECT (multiple children for the above Parent)
  CHILD_ID
  PARENT_ID
  ATTR1
  ...
  ATTRn

  CHILD_ID
  PARENT_ID
  ATTR1
  ATTRn

NEW_TABLE是一个表格,我们将根据PARENT和CHILD对象插入行

PL SQL查询使用两个嵌套的Cursors:

DECLARE
  CURSOR PARENT_CURSOR IS select * from PARENT_OBJECT;

BEGIN
 FOR PARENT_ROW in PARENT_CURSOR
    LOOP
      INSERT INTO NEW_TABLE values (PARENT_ID, ATTR1,...,ATTRn);

       OPEN CHILD_CURSOR FOR select * from CHILD_OBJECT where PARENT_ID = PARENT_ROW.PARENT_ID
        LOOP
        FETCH CHILD_CURSOR into CHILD_ROW;
        exit when CHILD_CURSOR%notfound;

        insert into NEW_TABLE values (PARENT_ID, ATTR1,...,ATTRn);
        END LOOP;
        CLOSE CHILD_CURSOR
  END LOOP;
END;

运行上述操作时,需要花费几个小时才能运行。 PARENT表有大约37000条记录,每个Parent在子级中平均有2个对象。

如何修改以提高性能?

1 个答案:

答案 0 :(得分:0)

正如@a_horse_with_no_name所说,没有必要使用PLSQL块。因此,您只需在Pure SQL中执行此操作:

INSERT INTO NEW_TABLE
     VALUES (PARENT_ID, ATTR1,...,ATTRn);
/     
INSERT INTO NEW_TABLE
   SELECT CO.*
     FROM CHILD_OBJECT CO
          INNER JOIN PARENT_OBJECT PO ON CO.PARENT_ID = PO.PARENT_ID;
Commit;

但是,如果您真的觉得需要PLSQL,那么您可以使用BULK操作来插入如下记录:

-- Assumptions
--1) New table has same columns as of Parent and Child table 
--2) Child and Paraent table have same columns.

DECLARE
   CURSOR REC_CURSOR
   IS
      SELECT * FROM PARENT_OBJECT
      UNION ALL
      SELECT *
        FROM CHILD_OBJECT
             INNER JOIN PARENT_OBJECT
                ON CHILD_OBJECT.PARENT_ID = PARENT_ROW.PARENT_ID;

   TYPE var_rec IS TABLE OF REC_CURSOR%ROWTYPE
      INDEX BY PLS_INTEGER;

   v_rec   var_rec;
BEGIN
   OPEN REC_CURSOR;

   LOOP
      FETCH REC_CURSOR BULK COLLECT INTO v_rec LIMIT 100;

      EXIT WHEN (v_rec.COUNT = 0);

      FORALL i IN 1 .. v_rec.COUNT
         INSERT INTO NEW_TABLE
              VALUES (v_rec (i));
   END LOOP;

   CLOSE REC_CURSOR;

   COMMIT;
END;