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

쿠폰 쓴 판매 8천 건을 세는데 판매 50만 건을 다 읽는다

기초SELECT유통37 / 700

상황 ​

유통 본사 마케팅팀의 「모바일 쿠폰 캠페인 실적」 화면은 캠페인별로 쿠폰을 쓴 판매 건수를 보여 준다. 캠페인 담당 네 명이 열어 두고, 화면 위쪽 숫자는 5분마다 새로 고친다. 지난달 DBA가 CPN_NO에 인덱스를 만들었는데 계획은 그대로다. 개발자는 "쿠폰을 안 쓴 판매는 NULL이라서 NVL로 걸러 냈다"라고 한다.

테이블과 인덱스 ​

  • CF10 판매: 500,000행 · 4,583블록(전체 스캔 4,510)
  • CPN_NO VARCHAR2(10): 모바일 쿠폰 캠페인 번호('MC2306A') · 쿠폰을 쓴 판매에만 값이 있고 나머지는 NULL · 값이 있는 행 7,812건(1.6%) · 캠페인 24종 · 'NONE'이라는 캠페인 번호는 없다 (문제 설정: 교재의 CF10에는 이 컬럼이 없다. 2023년 모바일 쿠폰을 도입하며 더한 컬럼이라고 본다)
  • 인덱스 IX_CF10_CPN (CPN_NO): 지난달 생성 · BLEVEL 1 · 리프 23블록 · 통계 최신(NUM_NULLS 492,188)

원본 SQL ​

sql
SELECT CPN_NO, COUNT(*) AS use_cnt
  FROM CF10
 WHERE NVL(CPN_NO, 'NONE') <> 'NONE'
 GROUP BY CPN_NO

실행계획 학습용 예시 ​

xplan
-------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |      1 |        |     24 |00:00:00.05 |    4510 |
|   1 |  HASH GROUP BY     |      |      1 |     24 |     24 |00:00:00.05 |    4510 |
|*  2 |   TABLE ACCESS FULL| CF10 |      1 |  25000 |   7812 |00:00:00.05 |    4510 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(NVL("CPN_NO",'NONE')<>'NONE')

문제 ​

  1. 인덱스가 있는데도 테이블 전체를 읽는 이유를 설명하시오. 판매 50만 건짜리 테이블인데 IX_CF10_CPN의 리프가 23블록밖에 안 되는 이유도 설명하시오.
  2. 결과가 바뀌지 않게 SQL을 고쳐 인덱스만 읽도록 하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자