oracle 大批量数据更新

 

现场如下:

有表

A(ID,CODE,C....C1,C2,C3),300W数据。C1,C2,C3是空的

B(ID,CODE,C.....C1,C2,C3),1万数据

现在要将A表中的C1到C3几个字段通过关联查询B表更新。

自己尝试了几个方案:不仅速度慢,还容易报错:ORA-01555: 快照过旧: 回退段号 6352 (名称为 "_SYSSMU6352_1445123658$") 过小

 

方案1:直接关联查询更新:

MERGE INTO YTRUT.T_RUT_WAYBILL_SUM A
USING (SELECT K.CODE,
              K.MANAGEMENT_AREA,
              K.REGION_MANAGE,
              K.TRANSPORT_CENTER,
              K.BRANCH,
              K.SUB_DEPARTMENT
         FROM YTMDM.MV_MDM_ORG_RPT K) B
ON (A.ORIG_ORG = B.CODE)
WHEN MATCHED THEN
  UPDATE
     SET A.DEST_MANAGEMENT_AREA  = B.MANAGEMENT_AREA,
         A.DEST_REGION_MANAGE    = B.REGION_MANAGE,
         A.DEST_TRANSPORT_CENTER = B.TRANSPORT_CENTER,
         A.DEST_BRANCH           = B.BRANCH,
         A.DEST_SUB_DEPARTMENT   = B.SUB_DEPARTMENT;
COMMIT;

这样发现效率太慢,事物太大,========================

方案2:

用指针,

又分2中情况:

1是在来源表用CURSOR,

DECLARE
  CURSOR CUR_ORG IS
    SELECT K.CODE,
           K.MANAGEMENT_AREA,
           K.REGION_MANAGE,
           K.TRANSPORT_CENTER,
           K.BRANCH,
           K.SUB_DEPARTMENT
      FROM YTMDM.MV_MDM_ORG_RPT K;
  C_ROW CUR_ORG%ROWTYPE;
BEGIN

  FOR C_ROW IN CUR_ORG LOOP
    UPDATE YTRUT.T_RUT_WAYBILL_SUM A
       SET A.DEST_MANAGEMENT_AREA  = C_ROW.MANAGEMENT_AREA,
           A.DEST_REGION_MANAGE    = C_ROW.REGION_MANAGE,
           A.DEST_TRANSPORT_CENTER = C_ROW.TRANSPORT_CENTER,
           A.DEST_BRANCH           = C_ROW.BRANCH,
           A.DEST_SUB_DEPARTMENT   = C_ROW.SUB_DEPARTMENT
     WHERE A.ORIG_ORG = C_ROW.CODE
       AND A.TARGET_DAY = TRUNC(SYSDATE) - 4;
    COMMIT;
  
    UPDATE YTRUT.T_RUT_WAYBILL_SUM A
       SET A.DEST_MANAGEMENT_AREA  = C_ROW.MANAGEMENT_AREA,
           A.DEST_REGION_MANAGE    = C_ROW.REGION_MANAGE,
           A.DEST_TRANSPORT_CENTER = C_ROW.TRANSPORT_CENTER,
           A.DEST_BRANCH           = C_ROW.BRANCH,
           A.DEST_SUB_DEPARTMENT   = C_ROW.SUB_DEPARTMENT
     WHERE A.DEST_ORG = C_ROW.CODE
       AND A.TARGET_DAY = TRUNC(SYSDATE) - 4;
    COMMIT;
  
  END LOOP;
END;

 

2,是在目标表用CURSOR

DECLARE
  CURSOR CUR_D IS
    SELECT DISTINCT T.DEST_ORG
      FROM YTRUT.T_RUT_WAYBILL_SUM T
     WHERE T.TARGET_DAY = TRUNC(SYSDATE) - 3;
  C_ROW CUR_D%ROWTYPE;
BEGIN
  --目的网点的  
  FOR C_ROW IN CUR_D LOOP
    MERGE INTO YTRUT.T_RUT_WAYBILL_SUM A
    USING (SELECT K.CODE,
                  K.MANAGEMENT_AREA,
                  K.REGION_MANAGE,
                  K.TRANSPORT_CENTER,
                  K.BRANCH,
                  K.SUB_DEPARTMENT
             FROM YTMDM.MV_MDM_ORG_RPT K
            WHERE K.CODE = C_ROW.DEST_ORG) B
    ON (A.DEST_ORG = B.CODE AND A.TARGET_DAY = TRUNC(SYSDATE) - 4)
    WHEN MATCHED THEN
      UPDATE
         SET A.DEST_MANAGEMENT_AREA  = B.MANAGEMENT_AREA,
             A.DEST_REGION_MANAGE    = B.REGION_MANAGE,
             A.DEST_TRANSPORT_CENTER = B.TRANSPORT_CENTER,
             A.DEST_BRANCH           = B.BRANCH,
             A.DEST_SUB_DEPARTMENT   = B.SUB_DEPARTMENT;
    COMMIT;
  END LOOP;
END;

 效率都很慢,

 

方案4:

使用中间表代替,先关联查询select将结果集放入中间表,再将原表数据清除,将中间表数据Insert进去

DECLARE
BEGIN
--STEP 1,清空临时表
  EXECUTE IMMEDIATE 'TRUNCATE TABLE YTRUT.T_RUT_WAYBILL_SUM_WCL';
  --TRUNCATE TABLE T_RUT_WAYBILL_SUM_WCL;
  --CREATE TABLE YTRUT.T_RUT_WAYBILL_SUM_WCL AS SELECT * FROM YTRUT.T_RUT_WAYBILL_SUM WHERE 1 = 2;
--STEP2,像临时表插入关联查询数据
  INSERT INTO YTRUT.T_RUT_WAYBILL_SUM_WCL
    SELECT T.ORIG_ORG,
           T.DEST_ORG,
           T.TOTAL_COUNT,
           T.TOTAL_WEIGHT,
           T.TARGET_DAY,
           T.ORIG_AREA,
           T.DEST_AREA,
           T.ORIG_PROVINCE,
           T.DEST_PROVINCE,
      ......
           T.COUNT_48H,
           T.WEIGHT_48H,
           K1.MANAGEMENT_AREA,
           K1.REGION_MANAGE,
           K1.TRANSPORT_CENTER,
           K1.BRANCH,
           K1.SUB_DEPARTMENT,
           K2.MANAGEMENT_AREA,
           K2.REGION_MANAGE,
           K2.TRANSPORT_CENTER,
           K2.BRANCH,
           K2.SUB_DEPARTMENT
      FROM YTRUT.T_RUT_WAYBILL_SUM T,
           YTMDM.MV_MDM_ORG_RPT    K1,
           YTMDM.MV_MDM_ORG_RPT    K2
     WHERE K1.CODE = T.ORIG_ORG
       AND K2.CODE = T.DEST_ORG
       AND T.TARGET_DAY = TRUNC(SYSDATE) - 2;
       
       commit;
       ----STEP3,将原表数据清除,
       DELETE FROM  YTRUT.T_RUT_WAYBILL_SUM T WHERE T.TARGET_DAY = TRUNC(SYSDATE) -2;
       commit;
       --STEP4,将临时表数据插入原表
       INSERT INTO YTRUT.T_RUT_WAYBILL_SUM SELECT * FROM YTRUT.T_RUT_WAYBILL_SUM_WCL ;
       commit;
END;

效果杠杠的!速度嗖嗖的!只用了不到半个小时就把几百万数据更新好了。

 

 

总结:

此类更新操作

无非是使用 CURSOR,LOOP,等循环批量操作数据,由于update是比较消耗资源的方法,会有undo和redo操作,因此换用insert效率上会快很多。

posted @ 2013-08-21 09:40  龙猫爸爸  阅读(2697)  评论(0编辑  收藏  举报