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

정산 테이블에 처음 만든 인덱스가 고객 한 명의 석 달 치에 50블록을 읽는다

기초DDL한빛유통90 / 700

상황 ​

야간 배치가 채우는 정산 테이블 T_ORD_STLM에는 인덱스가 하나도 없었다. 고객센터가 「고객 정산 내역」(고객 한 명의 석 달 치)을 쓰기 시작하자 조민우가 첫 인덱스를 만들었다. "범위 스캔을 하려면 범위 조건 컬럼이 맨 앞에 있어야 한다." 그래서 (STLM_DT, CUS_ID) 순서로 만들었다. 상담원 서른 명이 하루 6천 번쯤 연다. 아래는 고객 CUS_000123의 2024년 2분기다.

테이블과 인덱스 ​

  • T_ORD_STLM 정산: 100,000행 · 640블록 · 정산 배치가 매일 밤 비우고(TRUNCATE) T_ORD에서 직접 경로(APPEND)로 다시 채운다 · STLM_DT DATE(시분초 있음, 2023 ~ 2024, 하루 약 137건) · 고객당 50건
  • 2024년 2분기 정산: 12,467건 · 그중 CUS_000123은 6건
  • 인덱스 IX_STLM_DT_CUS (STLM_DT, CUS_ID): BLEVEL 1 · 리프 약 392블록(리프 한 블록에 약 255항목) · CLUSTERING_FACTOR 약 100,000 · 통계 최신

원본 SQL ​

sql
CREATE INDEX IX_STLM_DT_CUS ON T_ORD_STLM (STLM_DT, CUS_ID);

SELECT STLM_SEQ, ORD_SEQ, STLM_DT, STLM_AMT
  FROM T_ORD_STLM
 WHERE CUS_ID  = :v_cus
   AND STLM_DT >= TO_DATE(:v_from, 'YYYYMMDD')
   AND STLM_DT <  TO_DATE(:v_to, 'YYYYMMDD') + 1
 ORDER BY STLM_DT;

실행계획 학습용 예시 · 건수는 적재 스크립트 그대로 ​

xplan
-------------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                |      1 |        |      6 |00:00:00.01 |      56 |
|*  1 |  FILTER                      |                |      1 |        |      6 |00:00:00.01 |      56 |
|   2 |   TABLE ACCESS BY INDEX ROWID| T_ORD_STLM     |      1 |      6 |      6 |00:00:00.01 |      56 |
|*  3 |    INDEX RANGE SCAN          | IX_STLM_DT_CUS |      1 |      6 |      6 |00:00:00.01 |      50 |
-------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(TO_DATE(:V_TO,'YYYYMMDD')+1>TO_DATE(:V_FROM,'YYYYMMDD'))
   3 - access("STLM_DT">=TO_DATE(:V_FROM,'YYYYMMDD') AND "CUS_ID"=:V_CUS AND "STLM_DT"<TO_DATE(:V_TO,'YYYYMMDD')+1)
       filter("CUS_ID"=:V_CUS)

문제 ​

  1. 6건을 찾는 데 3번 줄이 50블록을 읽는 이유를 Predicate Information으로 설명하시오. 조민우의 말이 왜 틀렸는지도 설명하시오.
  2. 인덱스를 다시 설계해 DDL을 작성하고, 이 인덱스가 야간 적재에 주는 부담을 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자