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

PK에 상품번호가 들어 있는데 메뉴별 실적 조회가 테이블을 다 읽는다

중급SELECT유통06 / 700

상황 ​

유통 본사 MD가 쓰는 「메뉴별 판매 실적」 화면은 메뉴 하나를 고르면 2년치 판매 건수와 수량, 금액을 보여 준다. MD 여섯 명이 하루 수백 번 조회한다. 개발자는 이렇게 말한다. "PK에 ITM_NO가 있으니 인덱스를 탈 줄 알았다." 그래서 INDEX_SS 힌트를 붙여 봤는데 더 느려졌다. 아래는 콜드브루(1010)를 골랐을 때다.

테이블과 인덱스 ​

  • CF11 판매상품: 1,096,708행 · 8,204블록(블록당 약 134행) · 판매번호(SLE_NO) 순으로 적재되어 있다
  • CF11_PK (SLE_NO, ITM_NO): BLEVEL 2 · 리프 약 4,290블록 · SLE_NO 500,000종(판매 한 건에 상품 평균 2.2개)
  • ITM_NO: 팔린 메뉴 88종 · 메뉴당 3,032 ~ 275,135행 · (ICE)아메리카노 275,135 · (HOT)아메리카노 202,156 · 중간쯤 메뉴 약 6,200 · 콜드브루 15,493행은 8,204블록 중 7,025블록에 흩어져 있다
  • 다른 인덱스 없음 · 통계 최신(ITM_NO 히스토그램 없음)

원본 SQL ​

sql
SELECT COUNT(*) AS sle_cnt, SUM(SLE_QTY) AS qty, SUM(SLE_QTY * SLE_UPRC) AS amt
  FROM CF11
 WHERE ITM_NO = :v_itm

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

xplan
[원본]
-------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |      1 |        |      1 |00:00:00.07 |    8206 |
|   1 |  SORT AGGREGATE    |      |      1 |      1 |      1 |00:00:00.07 |    8206 |
|*  2 |   TABLE ACCESS FULL| CF11 |      1 |  12463 |  15493 |00:00:00.07 |    8206 |
-------------------------------------------------------------------------------------
   2 - filter("ITM_NO"=:V_ITM)

[개발자의 시도 — /*+ INDEX_SS(CF11 CF11_PK) */]
---------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |         |      1 |        |      1 |00:00:00.11 |   11471 |
|   1 |  SORT AGGREGATE                      |         |      1 |      1 |      1 |00:00:00.11 |   11471 |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED| CF11    |      1 |  12463 |  15493 |00:00:00.10 |   11471 |
|*  3 |    INDEX SKIP SCAN                   | CF11_PK |      1 |  12463 |  15493 |00:00:00.05 |    4418 |
---------------------------------------------------------------------------------------------------------
   3 - access("ITM_NO"=:V_ITM)
       filter("ITM_NO"=:V_ITM)

문제 ​

  1. CF11_PK에 ITM_NO가 있는데도 원본이 FULL로 처리되는 이유와, INDEX SKIP SCAN이 오히려 더 많이 읽은(11,471) 이유를 설명하시오. SKIP SCAN이 효과를 보는 인덱스는 어떤 모양인지도 설명하시오.
  2. 보조 인덱스를 DDL로 제안하시오. ITM_NO 하나짜리 인덱스로 충분한지 숫자로 따져 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자