Skip to content
튜닝 연습DML과 배치 튜닝
DML-007

미결제 주문 2,191건을 취소하는 데 1분 32초가 걸린다

기초UPDATE한빛유통432 / 700

상황 ​

매달 1일 03:00에는 지난달 미결제 주문(PENDING)을 취소(CANCEL)로 바꾸는 정리 배치가 돈다. 7월 1일에 6월분 2,191건을 정리하는 데 1분 32초가 걸렸다. 배치 담당 오과장: "겨우 2천 건인데요. UPDATE 한 건에 0.04초면 빠른 편 아닌가요?"

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 5,826블록. PK가 없고, ORD_SEQ는 값은 유일하지만 인덱스가 없다.
  • 인덱스는 IX_ORD_BIG_DT_AMT (ORD_DT, ORD_AMT) 하나다(정산 기간 조회 Q1용).
  • 2024년 6월 주문 27,390건 중 PENDING은 2,191건(8%)이다. 통계는 최신이다.

원본 SQL ​

sql
-- 매월 1일 03:00 · 지난달 미결제 주문 정리 (오과장)
BEGIN
  FOR r IN (SELECT ORD_SEQ
              FROM T_ORD_BIG
             WHERE ORD_DT >= DATE '2024-06-01'
               AND ORD_DT <  DATE '2024-07-01'
               AND ORD_ST = 'PENDING') LOOP
    UPDATE T_ORD_BIG
       SET ORD_ST = 'CANCEL'
     WHERE ORD_SEQ = r.ORD_SEQ;
  END LOOP;
  COMMIT;
END;

실행계획 학습용 예시 ​

xplan
[세션 통계 — 7월 1일 03:00 실행]
  경과 시간                 1분 32초 (거의 전부 CPU)
  session logical reads     12,777,640
  recursive calls           2,236
  갱신한 행                  2,191

[V$SQL — 루프 안의 UPDATE]
  SQL_TEXT                                                     EXECUTIONS  ROWS_PROCESSED  BUFFER_GETS   ELAPSED
  UPDATE T_ORD_BIG SET ORD_ST = 'CANCEL' WHERE ORD_SEQ = :B1        2,191           2,191   12,771,339   91.4 초

[그 UPDATE 한 번의 실행계획 — DISPLAY_CURSOR (ALLSTATS LAST)]
-------------------------------------------------------------------------------------------
| Id  | Operation          | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |           |      1 |        |      0 |00:00:00.04 |    5829 |
|   1 |  UPDATE            | T_ORD_BIG |      1 |        |      0 |00:00:00.04 |    5829 |
|*  2 |   TABLE ACCESS FULL| T_ORD_BIG |      1 |      1 |      1 |00:00:00.04 |    5826 |
-------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("ORD_SEQ"=:B1)

문제 ​

  1. UPDATE 한 건은 0.04초인데 배치가 1분 32초 걸리는 이유를 실행계획과 V$SQL로 설명하시오.
  2. 같은 결과를 내도록 고치고, ORD_SEQ에 인덱스를 만들어 루프를 그대로 두는 안과 비교하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자