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

「같은 달 두 해 비교」 화면이 어느 달을 골라도 판매 인덱스를 처음부터 끝까지 읽는다

실전SELECT유통61 / 700

상황 ​

유통 본사 「동월 비교」 화면은 달 하나(:v_mm)를 고르면 그달의 매장별 판매 건수를 해마다 나란히 보여 준다. 개발자는 연도를 따로 받지 않으려고 판매일자의 월 두 자리만 잘라 비교했다. 지금은 2022년과 2023년 두 해이고, 내년이면 2024년이 붙는다. 점장과 MD가 하루 수백 번 연다. 박팀장은 "고치는 방법 세 가지를 읽는 양, 해가 늘 때의 손질, 적재 부담으로 비교해 와라"고 했다.

테이블과 인덱스 ​

  • CF10 판매: 500,000행 · 4,583블록 · SLE_DT VARCHAR2(8) '20220101' ~ '20231231'(길이 8 고정) · SHP_NO NUMBER(5) 1001 ~ 1005 · 판매일자 순으로 쌓였다 · 한 달 약 2만 1천 건(2022년 6월 20,412건, 2023년 6월 20,953건)
  • 인덱스 CF10_PK (SLE_NO) · IX_CF10_DT_SHP (SLE_DT, SHP_NO): BLEVEL 2 · 리프 약 1,520블록(한 달 약 63블록) · 통계 최신
  • POS는 판매를 하루 약 700건 넣는다

원본 SQL ​

sql
SELECT SUBSTR(SLE_DT, 1, 4) AS yy, SHP_NO, COUNT(*) AS sle_cnt
  FROM CF10
 WHERE SUBSTR(SLE_DT, 5, 2) = :v_mm
 GROUP BY SUBSTR(SLE_DT, 1, 4), SHP_NO
 ORDER BY yy, SHP_NO

실행계획 학습용 예시 ​

xplan
[6월(:v_mm = '06')]
----------------------------------------------------------------------------------------------------
| Id  | Operation              | Name           | Starts | E-Rows | A-Rows | A-Time      | Buffers |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |                |      1 |        |     10 | 00:00:00.09 |    1532 |
|   1 |  SORT GROUP BY         |                |      1 |     10 |     10 | 00:00:00.09 |    1532 |
|*  2 |   INDEX FAST FULL SCAN | IX_CF10_DT_SHP |      1 |   5000 |  41365 | 00:00:00.07 |    1532 |
----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(SUBSTR("SLE_DT",5,2)=:V_MM)

문제 ​

  1. 인덱스의 선두 컬럼이 SLE_DT인데도 2번 줄이 범위 스캔이 아닌 이유를, 6월 판매가 인덱스의 어디에 있는지로 설명하시오.
  2. ① 해마다 앞부분 일치를 OR로 잇기 ② 해 목록을 행으로 만들어 조인하기 ③ 월 컬럼(가상 컬럼이나 함수 기반 인덱스) 더하기를 읽는 양, 해가 늘 때의 손질, 적재 부담으로 비교하시오.
  3. 채택한 방법을 SQL로 작성하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자