더북(TheBook)

한 번에 108건씩, 총 10,000번에 걸쳐 UPDATE를 수행하는데 대략 39초가 걸렸다. 하지만 FORALL문을 사용하면 수행시간이 확연히 줄어 든다. 이번엔 FORALL문을 사용해 보자.

입력

    DECLARE
      -- 커서 선언
      CURSOR c1 IS
      SELECT DISTINCT bulk_id
        FROM emp_bulk;

      -- 컬렉션 타입 선언
      TYPE BulkIDTP IS TABLE OF emp_bulk.bulk_id%TYPE;

      -- BulkIDTP형 변수 선언
      vnt_BulkID    BulkIDTP;

      vd_sysdate    DATE;
      vn_total_time NUMBER := 0;

    BEGIN
      -- 시작 전 vd_sysdate에 현재시간 설정
      vd_sysdate := SYSDATE;

      OPEN c1;

      -- BULK COLLECT 절을 사용해 vnt_BulkID 변수에 데이터 담기
      FETCH c1 BULK COLLECT INTO vnt_BulkID;

      -- 루프를 돌리지 않고 DELETE
      FORALL i IN 1..vnt_BulkID.COUNT
      UPDATE emp_bulk
        SET retire_date = hire_date
       WHERE bulk_id = vnt_BulkID(i);

      COMMIT;

      CLOSE c1;

      -- 총 소요 시간 계산(초로 계산하기 위해 60 * 60 * 24을 곱함)
      vn_total_time := (SYSDATE - vd_sysdate) * 60 * 60 * 24;

      -- 컬렉션 변수인 vnt_bkEmpTP 요소 개수 출력
      DBMS_OUTPUT.PUT_LINE('전체건수 : ' || vnt_BulkID.COUNT);
      -- 총 소요 시간 출력
      DBMS_OUTPUT.PUT_LINE('FORALL 소요시간 : ' || vn_total_time);
    END;

결과

    전체건수 : 10000
    FORALL 소요 시간 : 15.00000000000000000000000000000000000005

FOR LOOP를 사용한 것에 비해 대략 반 정도 빨라졌다. 어떤 환경에서 테스트 하느냐에 따라 수행시간은 달라질 수 있지만 대부분 FORALL문이 빠르다. UPDATE 뿐만 아니라 FORALL문과 함께 INSERT, DELETE, MERGE문도 사용할 수 있다.

이번 예제는 일반적인 커서와 반복문 내부에서 DML문을 사용하는 것보다는 FORALL문을 사용하는 것이 훨씬 좋은 성능을 발휘함을 보여주려고 만든 예제이고, 실제로는 FOR LOOP나 FORALL과 함께 DML문을 사용하기 보다는 SQL 문장만 사용해 처리할 때가 더 많다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.