大表oracle上的数据库更新花费了大量时间

时间:2016-12-22 05:54:36

标签: oracle performance

我想将一个列数据复制到包含10百万条记录的大表中的另一列中。 我使用sys refcursor将数据从一列复制到另一列。复制数据需要30多分钟。我使用的是ORACLE 11gR2。

还有其他方法可以做同样的事。以下是脚本

CREATE OR REPLACE PROCEDURE tblCursor(org_mig OUT SYS_REFCURSOR)
IS
  BEGIN
    OPEN org_mig FOR
    select id from tbl;
  END;
/
DECLARE
  org_mig SYS_REFCURSOR;
  t_id organization.id%TYPE;
  loop_var number(10);
  commit_interval number(10);
BEGIN
  loop_var :=1;
  commit_interval:=10000;
  tblCursor(org_mig);

  LOOP
    FETCH org_mig INTO t_id;
    EXIT WHEN org_mig%NOTFOUND;
    update tbl set col1=col2 where id=t_id;
    IF mod(loop_var,commit_interval)=0 THEN
      Commit;
    End if;
    loop_var :=loop_var+1;
  END LOOP;
  Commit;
  CLOSE org_mig;
END;
/

2 个答案:

答案 0 :(得分:1)

你在tbl的每一行都这样做,对吗?如果是这样,你应该这样做:

update tbl
set col1 = col2
/

更新一千万行需要一些时间,但是设置操作方式比你实现的Row By Agonizing Row方法更快。另外,批量提交这样的提交是不好的做法。它不仅会减慢速度,而且会导致ORA-01555: Snapshot too old例外。 Find out more

答案 1 :(得分:0)

Still it has been taken long time to update.


I am trying with different one but getting error. 

-----------------------------------
Error starting at line : 43 in command -
SELECT *
FROM  TABLE(test_parallel_update(CURSOR(SELECT * FROM organization)))
Error report -
SQL Error: ORA-12801: error signaled in parallel query server P003
ORA-00932: inconsistent datatypes: expected - got -
ORA-06512: at "QA249.TEST_PARALLEL_UPDATE", line 21
12801. 00000 -  "error signaled in parallel query server %s"
*Cause:    A parallel query server reached an exception condition.
*Action:   Check the following error message for the cause, and consult
           your error manual for the appropriate action.
*Comment:  This error can be turned off with event 10397, in which
           case the server's actual error is signaled instead.

---------------------------
Here is the script:




CREATE OR REPLACE TYPE test_num_arr AS TABLE OF NUMBER;
CREATE OR REPLACE FUNCTION test_parallel_update (
    test_cur IN SYS_REFCURSOR
) 
RETURN test_num_arr
PARALLEL_ENABLE (PARTITION test_cur BY ANY)
PIPELINED
IS
    PRAGMA AUTONOMOUS_TRANSACTION;

    test_rec organization%ROWTYPE;
    TYPE num_tab_t IS TABLE OF NUMBER(10,0);
    TYPE vc2_tab_t IS TABLE OF number(1,0);

    id NUM_TAB_T;
    org_type_old NUM_TAB_T;
    IS_DELETED_old VC2_TAB_T;

    cnt INTEGER := 0;
BEGIN
    LOOP
        FETCH test_cur BULK COLLECT INTO id, org_type_old, IS_DELETED_old LIMIT 1000;
        EXIT WHEN id.COUNT() = 0;

        FORALL i IN id.FIRST .. id.LAST
            UPDATE organization 
            SET    org_type = org_type_old(i)
            ,      IS_DELETED = IS_DELETED_old(i)
            WHERE  id = id(i);

        cnt := cnt + id.COUNT;
    END LOOP;

        CLOSE test_cur;

    COMMIT;
    PIPE ROW(cnt);
    RETURN;
END;
/
show error;
---- To Execute ----
SELECT *
FROM  TABLE(test_parallel_update(CURSOR(SELECT * FROM organization))); 



Note: 
Table
organization
(
id number(10,0),
org_type number(10,0),
org_type_old number(10,0),
IS_DELETED number(1,0),
IS_DELETED_OLD number(1,0)
);

where id is a primary key, Now I want copy org_type_old and IS_DELETED_OLD into org_type and IS_DELETED respectively.