Array Proccessing (다중처리)
- 한번 DBMS CALL에 여러건의 DATA를 처리하는 방법
- DBMS CALL은 시스템 Overhead의 주범
- Array Processing은 시스템 Overhead를 감소
- ARRAY SIZE는 사용자가 지정 가능하나 지나치면 Overhead 발생
(적절한 크기에서 10배 더 크게 잡아도 성능은 2배도 차이가 안남)
- 작성방법이 3GL과 차이가 많이 나므로 개발자들의 인식전환이 필요함
- 한번 FETCH 시 여러건을 동시에 ACCESS
- ACCESS와 동시에 DATA의 가공처리
- ACCESS 되면서 INSERT, UPDATE 구별
- 여러 건을 동시에 INSERT 혹은 UPDATE
Array Processing 예제
1. 상황
은행에서 일일 50만건의 손님의 업무를 봐준다.
신규 고객의 경우는 계좌정보에 INSERT를 해야하며, 기존 고객의 경우는 UPDATE를 해줘야 한다.
A, B Table의 벤다이어그램으로 생각을 해보면 겹쳐지는 부분은 UPDATE 영역이 될 것이며, A에만 속한 부분은 INSERT 영역이 될것이다.
UPDATE 시 보통 Unique Index를 활용하여 ROW를 ACCESS 하는데, 이건 정말 느린 방법이다. 대부분의 작업은 그전에 미리 SELECT 를 하므로 B TABLE의 ROWID를 알아 낼수가 있다. ROWID로 접근을 하는것이 가장 빠른 방법이겠다. 한걸음 더 나아가 생각을 해본다면 ROWID 순으로 SORTING을 한다면 연속된 BLOCK에 UPDATE를 자주하게 됨으로 더 빠른 실행이 가능 할것이다.
2. Non Array Processing 예제
위와 같은 실행은 엄청난 DBMS CALL Overhead를 유발하여 실행시간이 엄청 느리다.
그럼 Array Processing 으로 할려면 어떻게 해야 할까 ?
3. Array Processing 예제
ARRAY SIZE가 100개인 경우
IF 100개의 ARRAY 중 첫번쨰가 NULL이면 100개 모두 INSERT
ELSE 마지막이 NULL 이면 UPDATE, INSERT 같이 해야 하는 경우,
ELSE 100개 모두 UPDATE 로 실행한다.
중간에 UPDATE, INSERT 같이해야 하는 경우에는
ROWID가 NULL이면 INSERT, 아니면 UPDATE를 실행하면 된다.
- 한번 DBMS CALL에 여러건의 DATA를 처리하는 방법
- DBMS CALL은 시스템 Overhead의 주범
- Array Processing은 시스템 Overhead를 감소
- ARRAY SIZE는 사용자가 지정 가능하나 지나치면 Overhead 발생
(적절한 크기에서 10배 더 크게 잡아도 성능은 2배도 차이가 안남)
- 작성방법이 3GL과 차이가 많이 나므로 개발자들의 인식전환이 필요함
- 한번 FETCH 시 여러건을 동시에 ACCESS
- ACCESS와 동시에 DATA의 가공처리
- ACCESS 되면서 INSERT, UPDATE 구별
- 여러 건을 동시에 INSERT 혹은 UPDATE
Array Processing 예제
1. 상황
은행에서 일일 50만건의 손님의 업무를 봐준다.
신규 고객의 경우는 계좌정보에 INSERT를 해야하며, 기존 고객의 경우는 UPDATE를 해줘야 한다.
A, B Table의 벤다이어그램으로 생각을 해보면 겹쳐지는 부분은 UPDATE 영역이 될 것이며, A에만 속한 부분은 INSERT 영역이 될것이다.
UPDATE 시 보통 Unique Index를 활용하여 ROW를 ACCESS 하는데, 이건 정말 느린 방법이다. 대부분의 작업은 그전에 미리 SELECT 를 하므로 B TABLE의 ROWID를 알아 낼수가 있다. ROWID로 접근을 하는것이 가장 빠른 방법이겠다. 한걸음 더 나아가 생각을 해본다면 ROWID 순으로 SORTING을 한다면 연속된 BLOCK에 UPDATE를 자주하게 됨으로 더 빠른 실행이 가능 할것이다.
2. Non Array Processing 예제
EXEC SQL_BEGIN DECLARE section; VARCHAR v_jongcode[8]; INT v_cprice; VARCHAR v_dsum_rowid[20]; EXEC SQL_END DECLARE SECTION; EXEC SQL DECLARE c1 CURSOR FOR SELECT a.jongcode, a.cprice, b.rowid FROM dprice_c a, dsum_s b WHERE a.jongcode like '45%' AND a.jongcode = b.jongcode(+) AND a.cdate = b.cdate(+); EXEC SQL OPEN c1; for(;;) { EXEC SQL FETCH c1 INTO :v_jongcode, :v_cprice, :v_dsum_rowid; if (sqlca.sqlcode == 1403) break; EXEC SQL UPDATE DSUM_S SET csum = csum + :v_cprice WHERE ROWID = :v_dsum_rowid; if (sqlca.sqlcode == 1403) EXEC SQL INSERT INTO DSUM_S values (:v_jongcode, '19940829', :v_cprice); EXEC SQL COMMIT WORK; } EXEC SQL CLOSE c1; EXEC SQL COMMIT WORK RELEASE;위 예제는 한건 한건 따로 UPDATE 와 INSERT를 해주는 PL/SQL이다.
위와 같은 실행은 엄청난 DBMS CALL Overhead를 유발하여 실행시간이 엄청 느리다.
그럼 Array Processing 으로 할려면 어떻게 해야 할까 ?
3. Array Processing 예제
#define ARRAY_SIZE 100 EXEC SQL BEGIN DECLARE SECTION; INT v_num[ARRAY_SIZE]; VARCHAR v_fld1[ARRAY_SIZE][10]; VARCHAR v_rowid[ARRAY_SIZE][20]; SHORT i_rowid[ARRAY_SIZE]; INT loop; EXEC SQL END DECLARE SECTION; ... EXEC SQL DECLARE C1 CURSOR FOR SELECT a.num1, a.fld1, b.rowid FROM TABLE1 a, TABLE2 b WHERE a.fld1 = b.fld2(+) ORDER BY B.ROWID; EXEC SQL OPEN c1; indt = 1; whild (indt) { EXEC SQL FETCH c1 INTO :v_num1, :v_fld1, :v_rowid, i_rowid; if (sqlca.sqlcode = 1403) indt = 0; loop = sqlca.sqlerrd[2] - num_ret; num_ret = sqlca.sqlerrd[2]; -- Reset the number -- row id is null at the first row fetched if (i_rowid[0] == -1) { process_up_ins(0); -- INSERT ONLY } else { -- rowid is null at the last row fetched if (i_rowid[loop - 1] == -1) { process_up_ins(1); -- UPDATE AND INSERT BOTH } else { process_up_ins(2); -- UPDATE ONLY } } EXEC SQL COMMIT WORK; } EXEC SQL CLOSE c1; EXEC SQL COMMIT WORK RELEASE; rrocess_up_ins(proc_flag) int proc_flag; { if (proc_flag == 2) { EXEC SQL FOR :loop UPDATE TABLE2 SET num2 = num2 + :v_num1 WHERE ROWID = :v_rowid; } else if (proc_flag == 1 { EXEC SQL FOR :loop INSERT INTO TABLE2 SELECT :v_fld1, :v_num1 FROM dual WHERE :v_rowid IS NULL; EXEC SQL FOR :loop UPDATE TABLE2 SET num2 = num2 + :v_num1 WHERE :v_rowid IS NOT NULL AND ROWID = :v_rowid; } else { EXEC SQL FOR :loop INSERT INTO TABLE2 VALUES (:v_fld1, :v_num1); } }
ARRAY SIZE가 100개인 경우
IF 100개의 ARRAY 중 첫번쨰가 NULL이면 100개 모두 INSERT
ELSE 마지막이 NULL 이면 UPDATE, INSERT 같이 해야 하는 경우,
ELSE 100개 모두 UPDATE 로 실행한다.
중간에 UPDATE, INSERT 같이해야 하는 경우에는
ROWID가 NULL이면 INSERT, 아니면 UPDATE를 실행하면 된다.
댓글 없음:
댓글 쓰기