存储过程花费的时间太长,是否有更好的方法来进行此操作/优化?

时间:2018-08-29 20:35:50

标签: sql oracle plsql

当前,我正在尝试通过数据库链接批量插入大量数据(〜500,000行)。我正在从物化视图中获取数据。我本打算添加索引,但在某处读到它实际上会减慢该过程的速度。插入行后,我将获取唯一ID,并将其插入到标记表中,以便将它们标记为“已插入”,而不会再次插入。但是,此过程现在已停留约30分钟。有一个更好的方法吗? (下面是我的代码)。

create or replace PROCEDURE   SEND_DATA
IS
   CURSOR cursora
   IS
      SELECT DISTINCT unique_id_1
        FROM mv_1;

   CURSOR cursorb
   IS 
      SELECT DISTINCT unique_id_2
       FROM mv_2;

ca cursora%ROWTYPE;
cb cursorb%ROWTYPE;

    sent_flag NUMBER(10);
BEGIN
    SELECT flag_id
     INTO sent_flag
     FROM flag f
    WHERE f.flag_tx = 'SENT';
---
Delete FROM TABLE1@db1
      WHERE to_date(to_char(LOCAL_TIMESTAMP,'mm/dd/yyyy'),'mm/dd/yyyy') || code in 
 (SELECT distinct to_date(to_char(LOCAL_TIME_TS,'mm/dd/yyyy'),'mm/dd/yyyy'), code FROM MV_1);
COMMIT;
    Delete FROM TABLE1@db1 
          WHERE type || timestamp in (SELECT DATA_Type_TX || UTC_TS FROM MV_1);
    COMMIT;
    insert into TABLE1@db1(DATE, TYPE, VALUE, LAST_UPDATE, FLAG, LOCAL_TIMESTAMP)
    SELECT DATA_DATE,  NAME, VALUE, SYSDATE, null, LOCAL_TIME
  FROM MV_2 A;

COMMIT;
OPEN cursora;

LOOP
 FETCH cursora into ra;
 EXIT WHEN cursora%NOTFOUND;
 INSERT INTO flag(
    SUBMIT_ID,
    FLAG_ID,
    CREATE_USER_ID,
         CREATE_DT)
   VALUES (
    rdba.SUBMIT_ID,
    SENT_FLAG,
    '1',
         sysdate);
END LOOP;
CLOSE cursora;
COMMIT;
---
EXCEPTION
      WHEN OTHERS
      THEN
           NULL;
       RAISE;
    END SEND_DATA;

1 个答案:

答案 0 :(得分:2)

您的程序存在一些缺陷,实际上应该会失败。

create or replace PROCEDURE   SEND_DATA IS
   CURSOR cursora IS
      SELECT DISTINCT unique_id_1
        FROM mv_1;

   CURSOR cursorb IS 
      SELECT DISTINCT unique_id_2
       FROM mv_2;

过程中未使用游标cursorb,为什么要声明它?

Delete FROM TABLE1@db1
      WHERE to_date(to_char(LOCAL_TIMESTAMP,'mm/dd/yyyy'),'mm/dd/yyyy') || code in 
 (SELECT distinct to_date(to_char(LOCAL_TIME_TS,'mm/dd/yyyy'),'mm/dd/yyyy'), code FROM MV_1);

这应该失败,因为首先要连接两列,但是在IN ()中要选择两列。无论如何,请删除DISTINCT子句-它没有用。

    Delete FROM TABLE1@db1 
          WHERE type || timestamp in (SELECT DATA_Type_TX || UTC_TS FROM MV_1);

您不应使用诸如TIMESTAMP之类的保留关键字作为列名。

LOOP
 FETCH cursora into ra;
 EXIT WHEN cursora%NOTFOUND;
 INSERT INTO flag(SUBMIT_ID, FLAG_ID, CREATE_USER_ID, CREATE_DT)
   VALUES ( rdba.SUBMIT_ID, SENT_FLAG, '1', sysdate);
END LOOP;

为什么要用引号将数字值括起来(即'1')?该代码也应该失败,因为未声明变量rardba。我认为是

LOOP
 FETCH cursora into ca;
 EXIT WHEN cursora%NOTFOUND;
 INSERT INTO flag(SUBMIT_ID, FLAG_ID, CREATE_USER_ID, CREATE_DT)
   VALUES ( ca.unique_id_1, SENT_FLAG, '1', sysdate);
END LOOP;

将其重写为

INSERT INTO flag (SUBMIT_ID, FLAG_ID, CREATE_USER_ID, CREATE_DT)
SELECT DISTINCT unique_id_1, SENT_FLAG, 1, sysdate
FROM mv_1;

假设以上内容会给出正确的逻辑

EXCEPTION
      WHEN OTHERS
      THEN
           NULL;
       RAISE;

这部分完全没有用。 WHEN OTHERS THEN NULL;的意思是“忽略任何错误”,但在下一行将其引发。