FORALL 문으로 수행한 DML 문의 수행 횟수는 FORALL 문의 수행 횟수로 기록됩니다. 이로 인해 SQL 실행 통계 분석 시 주의가 필요합니다.
테스트를 위해 아래와 같이 테이블을 생성하겠습니다. t1 테이블은 1,000,000개의 로우를 가지고 있습니다.
-- 1
DROP TABLE t1 PURGE;
DROP TABLE t2 PURGE;
CREATE TABLE t1 (c1, c2) AS SELECT ROWNUM, LPAD ('X', 100, 'X') FROM XMLTABLE ('1 to 1000000');
CREATE TABLE t2 AS SELECT * FROM t1 WHERE 0 = 1;
아래와 같이 1,000건 단위로 Bulk Insert를 수행하겠습니다. FORALL 문은 1,000회(= 1,000,000 / 1,000) 반복 수행됩니다.
-- 2
DECLARE
CURSOR cur_t1 IS SELECT * FROM t1;
TYPE tnt_t1 IS TABLE OF t1%ROWTYPE;
v_t1 tnt_t1;
BEGIN
OPEN cur_t1;
LOOP
FETCH cur_t1 BULK COLLECT INTO v_t1 LIMIT 1000;
FORALL i IN v_t1.FIRST .. v_t1.LAST
INSERT /*+ TEST */ INTO t2 VALUES v_t1(i);
EXIT WHEN cur_t1%NOTFOUND;
END LOOP;
CLOSE cur_t1;
COMMIT;
END;
/
V$SQL 뷰를 조회해보면 수행 횟수(executions)가 1000으로 FORALL 문의 수행 횟수와 동일한 것을 확인할 수 있습니다. 이로 인해 1회 수행 당 평균 블록 I/O(gets_pe)가 131.19로 계산되며, INSERT VALUES 문을 한번 수행하는데 평균 131.19개의 블록 I/O가 발생한다고 오해석할 수 있습니다.
-- 3
SELECT sql_text
, executions
, buffer_gets
, rows_processed
, buffer_gets / executions AS gets_pe
, buffer_gets / rows_processed AS gets_pr
, rows_processed / executions AS rows_pe -- bulk size
FROM v$sql
WHERE sql_text LIKE 'INSERT /*+ TEST */%';
SQL_TEXT EXECUTIONS BUFFER_GETS ROWS_PROCESSED GETS_PE GETS_PR ROWS_PE
--------------------------------------------- ---------- ----------- -------------- ------- ------- -------
INSERT /*+ TEST */ INTO T2 VALUES (:B1 ,:B2 ) 1000 131187 1000000 131.19 0.13 1000
1개의 행이 선택되었습니다.