Skip to content
튜닝 연습인덱스 사용 조건
IDX-047

DBA가 만든 배송요청일 인덱스를 두고도 택배 연계 배치는 주문 100만 건을 다 읽는다

실전UPDATE한빛유통47 / 700

상황 ​

한빛유통은 결제가 끝난 주문(COMPLETE)을 5분마다 모아 택배사에 배송을 요청한다. 연계 배치는 보낼 주문에 요청 시각을 찍으면서 그 주문번호를 돌려받아 택배사 연계 테이블에 넣는다. 한 번에 300건 안팎인데 한 번 도는 데 0.3초, 하루 288번 돈다. 지난주 DBA가 DLV_REQ_DT에 인덱스를 만들었지만 계획은 그대로다. 조민우는 (DLV_REQ_DT, 0)으로 다시 만들자고 하고, 오과장은 배송 대기 플래그 컬럼을 새로 두자고 한다. 박팀장은 대안을 비교하고 DML 쪽 대가까지 적어 오라고 했다.

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 6,816블록(배송 요청 컬럼을 더한 뒤) · ORD_SEQ 유일 · ORD_ST COMPLETE 90% · PENDING 8% · CANCEL 2%
  • DLV_REQ_DT DATE: 택배사에 배송을 요청한 시각 · 요청 전이면 NULL · 요청 대상은 COMPLETE뿐이라 PENDING 8만 건과 CANCEL 2만 건은 계속 NULL로 남는다 · 5분마다 새로 COMPLETE가 된 주문 약 300건이 NULL로 들어온다 (문제 설정: 교재의 T_ORD_BIG에는 이 컬럼이 없다. 배송 연계 개편 때 더한 컬럼이라고 본다)
  • 인덱스 IX_ORD_BIG_SEQ (ORD_SEQ) 유니크 · IX_ORD_BIG_DLV (DLV_REQ_DT): 지난주 생성 · 리프 2,650 · 통계 최신(NUM_NULLS 100,300)
  • 새로 COMPLETE가 된 주문은 대부분 테이블 끝에 쌓인 최근 주문이라, 한 번에 보낼 300건은 테이블 끝 블록 몇 개에 모여 있다

원본 SQL ​

sql
DECLARE
  TYPE t_seq_tab IS TABLE OF T_ORD_BIG.ORD_SEQ%TYPE;
  v_seq t_seq_tab;
BEGIN
  UPDATE T_ORD_BIG
     SET DLV_REQ_DT = SYSDATE
   WHERE ORD_ST = 'COMPLETE'
     AND DLV_REQ_DT IS NULL
  RETURNING ORD_SEQ BULK COLLECT INTO v_seq;

  PKG_DLV_IF.SEND(v_seq);          -- 택배사 연계 테이블에 넣는다
  COMMIT;
END;

실행계획 학습용 예시 ​

xplan
[UPDATE 한 번 · 300건]
---------------------------------------------------------------------------------------
| Id  | Operation          | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |           |      1 |        |      0 |00:00:00.31 |    7428 |
|   1 |  UPDATE            | T_ORD_BIG |      1 |        |      0 |00:00:00.31 |    7428 |
|*  2 |   TABLE ACCESS FULL| T_ORD_BIG |      1 |   9027 |    300 |00:00:00.29 |    6816 |
---------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(("DLV_REQ_DT" IS NULL AND "ORD_ST"='COMPLETE'))

문제 ​

  1. IX_ORD_BIG_DLV가 쓰이지 않는 이유를 설명하고, 조민우의 (DLV_REQ_DT, 0)도 이 배치를 빠르게 하지 못하는 이유를 숫자로 설명하시오.
  2. ① (DLV_REQ_DT, ORD_ST) 결합 인덱스 ② 보낼 주문만 담는 함수 기반 인덱스(또는 가상 컬럼) ③ 배송 대기 플래그 컬럼을 새로 두는 모델 변경을 비교하시오. 인덱스 크기와 UPDATE마다 드는 인덱스 유지 비용을 함께 따지시오.
  3. 고른 방법의 DDL과 고친 배치 SQL을 작성하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자