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

이번 달 메뉴 순위 칸이 2년 치 판매상품을 다 읽는다

기초SELECT유통07 / 700

상황 ​

유통 본사 대시보드의 「이번 달 메뉴 순위」 칸은 5분마다 새로 고쳐지고, MD들이 화면을 열 때마다 한 번 더 호출된다. 한 번에 8천 블록 넘게 읽어서 대시보드 전체가 굼뜨다는 말이 나왔다. 개발자는 이렇게 설명한다. "판매상품(CF11)에는 판매일자 컬럼이 없어서, 판매번호 앞 여섯 자리로 달을 잘랐다." 아래는 2023년 6월(:v_ym = '202306')을 조회했을 때다.

테이블과 인덱스 ​

  • CF11 판매상품: 1,096,708행 · 8,204블록(블록당 약 134행) · 판매번호 순으로 거의 정렬되어 적재되어 있다
  • SLE_NO VARCHAR2(15): 판매일자 8자리 + - + 그날의 일련번호 4자리('20230601-0488'). 판매번호 앞 8자리는 판매(CF10.SLE_DT)의 판매일자와 전부 같다
  • 2023년 6월 판매상품: 45,935행(4.19%) · 팔린 메뉴 88종 · 이 행들은 테이블 371블록에 모여 있다
  • 인덱스 CF11_PK (SLE_NO, ITM_NO): BLEVEL 2 · 리프 약 4,290블록 · 통계 최신 · 다른 인덱스 없음

원본 SQL ​

sql
SELECT ITM_NO, SUM(SLE_QTY) AS qty, SUM(SLE_QTY * SLE_UPRC) AS amt
  FROM CF11
 WHERE SUBSTR(SLE_NO, 1, 6) = :v_ym
 GROUP BY ITM_NO
 ORDER BY amt DESC

실행계획 학습용 예시 · 건수는 적재 데이터 그대로 ​

xplan
-------------------------------------------------------------------------------------------------
| Id  | Operation           | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Used-Mem |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |      1 |        |     88 |00:00:00.11 |    8206 |          |
|   1 |  SORT ORDER BY      |      |      1 |     88 |     88 |00:00:00.11 |    8206 | 6144  (0)|
|   2 |   HASH GROUP BY     |      |      1 |     88 |     88 |00:00:00.11 |    8206 | 1288K (0)|
|*  3 |    TABLE ACCESS FULL| CF11 |      1 |  10967 |  45935 |00:00:00.08 |    8206 |          |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   3 - filter(SUBSTR("SLE_NO",1,6)=:V_YM)

문제 ​

  1. CF11_PK의 선두 컬럼이 SLE_NO인데도 테이블 전체를 읽는 이유를 실행계획의 어느 줄에서 알 수 있는지 설명하시오.
  2. 결과가 바뀌지 않게 SQL을 고쳐 CF11_PK로 한 달 치 범위만 읽도록 하시오. 고친 조건이 원래 조건과 같은 행을 고르는 이유도 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자