요약1. 커서에 한번에 넣고2. Bulk Collect into XX Limit 40000
4만건단위로 XX data SET 처리 (배열??)3. FORALL
4만건 단위로 20번에 INSERT 처리
------------------------------------------------------------------------------------------------------------------------
특정 프로시져에서 CPU사용량이 높다고 이것을 튜닝해 달라고 요청이 왔는데
프로시져를 까보니 데이타를 80만건정도를 계속 INSERT시키는 그런 프로그램이었다.
80만건을 계속 INSERT한다는것 자체가 의심이 갔지만 일단 그렇게 해야한다고 하니 이것에 대해 분산처리할 수 있는 방법이 필요했다. 80만건을 INSERT SELECT로 한꺼번에 처리하면 CPU사용량도 늘어나지만 메모리사용량도 늘어난다.
여기서 Bulk Sql을 사용하면 CPU사용량은 비슷하지만 메모리 사용량은 분산처리할 수 있다.(구글링으로 알아낸 결과임.^^)
분산처리는 커서를 이용해 루프를 돌면서 특정건수(LIMIT) 만큼을 INSERT처리하는 방식이다.
예문을 보면서 알아보자.
[사용예]
CREATE OR REPLACE PROCEDURE SP_TEST AS
BEGIN
INSERT INTO SALES
SELECT *
FROM TT_DATA;
END;
- TT_DATA 테이블의 데이타가 80만건이라고 가정하자.
- SP_TEST 프로시져를 호출하면 SALES 테이블은 80만건이 다 들어갈때까지 LOCK이 걸리게 된다.
이것을 분산처리 방식으로 변경해 보자.
필자는 커서를 다이나믹쿼리로 구성했다.
[Bulk SQL 사용예]
CREATE OR REPLACE PROCEDURE SP_TEST AS
TYPE Gv_DATA_LIST IS TABLE OF SALES%ROWTYPE; -- TYPE 선언
Gv_DATA Gv_DATA_LIST; -- TYPE변수 할당
CUR1 SYS_REFCURSOR; -- 커서변수 선언
Gv_SelectSQL LONG := ' ';
--
BEGIN
Gv_SelectSQL := ' SELECT * FROM TT_DATA ';
--
OPEN CUR1 FOR
Gv_SELECTSQL;
LOOP
--
FETCH CUR1 BULK COLLECT INTO Gv_DATA LIMIT 40000;
--
FORALL I IN Gv_DATA.FIRST..Gv_DATA.LAST
INSERT INTO SALES VALUES Gv_DATA(I) ;
--
EXIT WHEN CUR1%NOTFOUND;
--
END LOOP;
END;
- 선언부에는 SALES 테이블을 TYPE변수로 선언한다.
- 커서변수를 선언한다.
(일반적으로 이곳에 쿼리를 넣을수도 있지만 필자는 다이나믹쿼리로 하기때문에 변수만 선언했다.) - 커서를 오픈후 루프를 돌면서 FETCH를 한다.(핵심1)
FETCH CUR1 BULK COLLECT INTO Gv_DATA LIMIT 40000; - FORALL문을 이용해서 데이타를 넣는다.(핵심2)
- FORALL I IN Gv_DATA.FIRST..Gv_DATA.LAST
- 40000건을 SQL1회로 처리하게 된다. - FOR문을 사용할 경우 SQL 40000회가 실행된다.
- 20번 루프를 돌면서 처리가 끝나게 된다.
- 40000만건씩 INSERT처리되기 때문에 다음 처리할때 여유있는 메모리를 사용할 수 있게 된다.
- 여러사람이 동시에 호출을 한다면 40000건이 INSERT된 후 대기하고 있던 사용자가 사용할 수 있게 된다.
'DB-Oracle' 카테고리의 다른 글
TOAD 사용 단축키 (0) | 2023.08.29 |
---|---|
UTL_URL.ESCAPE 인코딩, UTL_URL.UNESCAPE 디코딩 (0) | 2023.08.17 |
ORACLE DB생성, 사용자생성, GRANT (0) | 2023.08.09 |
ORDER BY nulls FIRST, case when 등등 가능 (0) | 2023.08.08 |
Oracle 세션관리 기초 (0) | 2023.08.08 |