DATOR


튜닝-함수의 병렬처리

데이터이행은 주로 대용량을 많이 처리 하기때문에 보통 PARALLEL을 사용해서
데어터를 처리 하고 있다.

 

기존 수행속도가 5분 이었는데 함수 하나 적용으로 인하여 3시간이 걸려도
답이 안나오는 경우가 있다.

 

그런경우 십중팔구 함수의 병렬처리가 제대로 안되어서 그런 경우가 많이 발생한다.

 

아래는 기존 튜닝전 소스

 
COMMIT;
ALTER SESSION ENABLE PARALLEL DML;
INSERT /*+ PARALLEL(A 16) */ INTO [macr("MIG_SCH")].MIG_MAP_SRV_SR_ACT_D PARTITION(STG_GBN_S_EVT_ACT) A
SELECT  /*+ FULL(S_EVT_ACT) PARALLEL(S_EVT_ACT 16) */
 'NOW'
,S_EVT_ACT.ROW_ID                       AS ROW_ID          ----서비스활동정보 ROW_ID
,S_EVT_ACT.ACTIVITY_UID                 AS ORG_ACTIVITY_UID----ACTIVITY_UID
,ASIS_ROWIDTOROWIDNUM(S_EVT_ACT.ROW_ID) AS ACTIVITY_UID    ----통합DB로이행되는 CONVERSION된 ACTIVITY_UID
,S_EVT_ACT.NAME                         AS NAME            ----서비스활동관련메일의 메일제목명
FROM [macr("SR_SIEBEL_SCH")].S_EVT_ACT;

데이터 처리건수:6천만건
실행시간:3시간

 

 

해당 함수
CREATE OR REPLACE FUNCTION ASIS_ROWIDTOROWIDNUM (PVALUE VARCHAR2)
RETURN VARCHAR2 IS
 NPOT1 NUMBER;
 NPOT2 NUMBER;
 SRET VARCHAR2(15);
BEGIN
 IF LENGTH(PVALUE) = 0 THEN
  RETURN NULL;
 END IF;
 NPOT1 := INSTR(PVALUE, '-',1, 1);
 NPOT2 := INSTR(PVALUE, '-',1, 2);
 IF NPOT1 = 0 THEN
  NPOT1 := INSTR(PVALUE, '+',1, 1);
  NPOT2 := INSTR(PVALUE, '+',1, 2);
 END IF;
 IF NPOT1 = 0 THEN
  SRET := B36TONUM(PVALUE);
 ELSE
  SRET := B36TONUM(SUBSTR(PVALUE,1,NPOT1-1))||SUBSTR(PVALUE,NPOT1,1);
  IF NPOT2 = 0 THEN
   SRET := SRET || B36TONUM(SUBSTR(PVALUE,NPOT1+1,LENGTH(PVALUE)-NPOT1));
  ELSE
   SRET := SRET || B36TONUM(SUBSTR(PVALUE,NPOT1+1,NPOT2-(NPOT1+1)))||SUBSTR(PVALUE,NPOT2,1);
   SRET := SRET || B36TONUM(SUBSTR(PVALUE,NPOT2+1,LENGTH(PVALUE)-NPOT2));
  END IF;
 END IF;
 RETURN SRET;
END ASIS_ROWIDTOROWIDNUM;

CREATE OR REPLACE FUNCTION [macr("MIG_SCH")].B36TONUM (PVALUE VARCHAR2)
RETURN VARCHAR2  IS
 II  NUMBER;
 NLEN NUMBER;
 NVAL NUMBER;
 CTOK CHAR;
 NRET NUMBER := 0;
BEGIN
 NLEN := LENGTH(PVALUE);
 FOR II IN 1..NLEN LOOP
  CTOK := SUBSTR(PVALUE,II,1);
  --dbms_output.put_line('CTOK'||CTOK);
  --dbms_output.put_line('CTOK'||ASCII(CTOK));
  IF ASCII(CTOK) < 65 THEN
     NVAL := ASCII(CTOK) - 48;
  ELSE
     NVAL := ASCII(CTOK) - 65 + 10;
  END IF;
  --dbms_output.put_line('NRET1'||NRET);
  NRET := NRET + (NVAL*36**(NLEN-II));
  --dbms_output.put_line('NRET2'||NRET);
 END LOOP;
 RETURN TO_CHAR(NRET);
END B36TONUM; 

문제점)
 1.기존 함수는 어뜬 테이블의 결과값을 가져오는 것이 아니고
   이미 정의된 함수이다.즉 변화하지 않는 결과값임
 2.해당 함수가 제대로 PARALLEL이 되지 않는 경우임.
 3.함수에 parallel_enable 을 추가해서 해결하면 됨.

 

함수 변경부분)
CREATE OR REPLACE FUNCTION [macr("MIG_SCH")].MIG_ROWIDTOROWIDNUM (PVALUE VARCHAR2)
RETURN VARCHAR2 parallel_enable IS
 NPOT1 NUMBER;
 NPOT2 NUMBER;
 SRET VARCHAR2(15);
BEGIN
 IF LENGTH(PVALUE) = 0 THEN
  RETURN NULL;
 END IF;
 NPOT1 := INSTR(PVALUE, '-',1, 1);
 NPOT2 := INSTR(PVALUE, '-',1, 2);
 IF NPOT1 = 0 THEN
  NPOT1 := INSTR(PVALUE, '+',1, 1);
  NPOT2 := INSTR(PVALUE, '+',1, 2);
 END IF;
 IF NPOT1 = 0 THEN
  SRET := B36TONUM(PVALUE);
 ELSE
  SRET := B36TONUM(SUBSTR(PVALUE,1,NPOT1-1))||SUBSTR(PVALUE,NPOT1,1);
  IF NPOT2 = 0 THEN
   SRET := SRET || B36TONUM(SUBSTR(PVALUE,NPOT1+1,LENGTH(PVALUE)-NPOT1));
  ELSE
   SRET := SRET || B36TONUM(SUBSTR(PVALUE,NPOT1+1,NPOT2-(NPOT1+1)))||SUBSTR(PVALUE,NPOT2,1);
   SRET := SRET || B36TONUM(SUBSTR(PVALUE,NPOT2+1,LENGTH(PVALUE)-NPOT2));
  END IF;
 END IF;
 RETURN SRET;
END MIG_ROWIDTOROWIDNUM;

 

CREATE OR REPLACE FUNCTION [macr("MIG_SCH")].B36TONUM (PVALUE VARCHAR2)
RETURN VARCHAR2  parallel_enable IS
 II  NUMBER;
 NLEN NUMBER;
 NVAL NUMBER;
 CTOK CHAR;
 NRET NUMBER := 0;
BEGIN
 NLEN := LENGTH(PVALUE);
 FOR II IN 1..NLEN LOOP
  CTOK := SUBSTR(PVALUE,II,1);
  --dbms_output.put_line('CTOK'||CTOK);
  --dbms_output.put_line('CTOK'||ASCII(CTOK));
  IF ASCII(CTOK) < 65 THEN
     NVAL := ASCII(CTOK) - 48;
  ELSE
     NVAL := ASCII(CTOK) - 65 + 10;
  END IF;
  --dbms_output.put_line('NRET1'||NRET);
  NRET := NRET + (NVAL*36**(NLEN-II));
  --dbms_output.put_line('NRET2'||NRET);
 END LOOP;
 RETURN TO_CHAR(NRET);
END B36TONUM;

튜닝후 소스


COMMIT;
ALTER SESSION ENABLE PARALLEL DML;
INSERT /*+ PARALLEL(A 16) */ INTO [macr("MIG_SCH")].MIG_MAP_SRV_SR_ACT_D PARTITION(STG_GBN_S_EVT_ACT) A
SELECT  /*+ FULL(S_EVT_ACT) PARALLEL(S_EVT_ACT 16) */
 'NOW'
,S_EVT_ACT.ROW_ID                                                                      AS ROW_ID                          ----서비스활동정보 ROW_ID
,S_EVT_ACT.ACTIVITY_UID                                                                AS ORG_ACTIVITY_UID                ----ACTIVITY_UID
,MIG_ROWIDTOROWIDNUM(S_EVT_ACT.ROW_ID)                               AS ACTIVITY_UID                    ----통합DB로이행되는 CONVERSION된 ACTIVITY_UID
,S_EVT_ACT.NAME                                                                        AS NAME                            ----서비스활동관련메일의 메일제목명
FROM [macr("SR_SIEBEL_SCH")].S_EVT_ACT
;
COMMIT;
 

 

 

결과시간)
5분
결과건수
6천만건

Tag

Leave Comments