Skip to content
튜닝 연습인덱스 스캔 효율과 테이블 액세스
ACC-007

하루 고액 주문 목록에 filter가 보인다며 인덱스를 하나 더 만들자고 한다

기초SELECT한빛유통82 / 700

상황 ​

리스크팀은 「하루 고액 주문」 목록을 하루 50번쯤 연다. 날짜 하나를 고르면 그날 49만 원 이상인 주문을 보여 준다. 실행계획을 보던 조민우가 이렇게 말했다. "Predicate에 filter가 있다. ORD_AMT가 access로 쓰이게 (ORD_DT, ORD_AMT) 인덱스를 하나 더 만들자." 아래는 2024년 6월 11일을 골랐을 때다.

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 5,826블록 · ORD_DT 하루 913건(전부 자정) · ORD_AMT 1만 ~ 50만 원에 고르게 분포(49만 원 이상 약 2%)
  • 인덱스 IX_ORD_BIG_DT_ST_AMT (ORD_DT, ORD_ST, ORD_AMT): 「일자별 상태별 매출」 화면용 · BLEVEL 2 · 리프 약 4,170블록(리프 한 블록에 약 240항목) · CLUSTERING_FACTOR 약 1,000,000 · 통계 최신
  • 다른 인덱스는 없다 · 운영에서는 주문이 계속 INSERT된다
  • 참고(교재 04화 실측): (ORD_DT, ORD_AMT) 인덱스는 리프 3,206블록이고, 인덱스 하나를 더 두면 주문 5만 건 적재에 redo가 약 11.8MB 는다

원본 SQL ​

sql
SELECT ORD_SEQ, CUS_ID, ORD_AMT
  FROM T_ORD_BIG
 WHERE ORD_DT  = TO_DATE(:v_dt, 'YYYYMMDD')
   AND ORD_AMT >= 490000
 ORDER BY ORD_SEQ

실행계획 학습용 예시 · 건수는 적재 스크립트 그대로 · 금액 분포는 어림값 ​

xplan
-----------------------------------------------------------------------------------------------------------------------
| Id  | Operation                             | Name                 | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |                      |      1 |        |     19 |00:00:00.01 |      25 |
|   1 |  SORT ORDER BY                        |                      |      1 |     18 |     19 |00:00:00.01 |      25 |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED | T_ORD_BIG            |      1 |     18 |     19 |00:00:00.01 |      25 |
|*  3 |    INDEX RANGE SCAN                   | IX_ORD_BIG_DT_ST_AMT |      1 |     18 |     19 |00:00:00.01 |       6 |
-----------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access("ORD_DT"=TO_DATE(:V_DT,'YYYYMMDD') AND "ORD_AMT">=490000)
       filter("ORD_AMT">=490000)

문제 ​

  1. 3번 줄에서 어느 조건이 읽을 범위를 정하고 어느 조건이 읽으면서 거르는지 설명하시오. ORD_AMT가 filter로 쓰인 이유도 인덱스 컬럼 순서로 설명하시오.
  2. 조민우의 제안을 받아들일지 숫자로 판단하시오. 새 인덱스를 만들면 무엇이 줄고 무엇이 그대로인지, 그 대가는 무엇인지 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자