Skip to content
튜닝 연습서브쿼리와 쿼리 변환
SUBQ-021

카테고리를 고르면 팔린 상품 일곱 개를 보여 주는 팝업이 판매상품 인덱스를 통째로 읽는다

기초SELECT유통256 / 700

상황 ​

본사 MD의 「행사 상품 고르기」 팝업은 카테고리를 고르면 그 카테고리 상품 가운데 한 번이라도 팔린 상품만 보여 준다. MD 열 명이 행사를 짤 때마다 카테고리를 바꿔 가며 눌러 하루 2천 번쯤 호출되고, 한 번에 0.05초 남짓 걸린다. DBA는 "0.05초짜리를 왜 보느냐"라고 하지만, 하루 합계로는 이 팝업이 판매상품 인덱스를 가장 많이 읽는다.

테이블과 인덱스 ​

  • CF01 상품: 109행 · 5블록 · CF01_PK (ITM_NO) · 카테고리 311(텀블러)에 상품 9개, 그중 판매 이력이 있는 상품 7개
  • CF11 판매상품: 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO) 리프 약 4,300블록 · ITM_NO로 시작하는 인덱스는 없다
  • 팔린 상품은 상품마다 판매 줄이 수천 ~ 수만 줄이다 · 통계 최신

원본 SQL ​

sql
SELECT p.ITM_NO, p.ITM_NM
  FROM CF01 p
 WHERE p.CTG_NO = :ctg
   AND EXISTS (SELECT 1
                 FROM CF11 b
                WHERE b.ITM_NO = p.ITM_NO)
 ORDER BY p.ITM_NO

실행계획 학습용 예시 ​

xplan
--------------------------------------------------------------------------------------------
| Id  | Operation              | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |         |      1 |        |      7 |00:00:00.05 |    4338 |
|   1 |  SORT ORDER BY         |         |      1 |      8 |      7 |00:00:00.05 |    4338 |
|*  2 |   HASH JOIN SEMI       |         |      1 |      8 |      7 |00:00:00.05 |    4338 |
|*  3 |    TABLE ACCESS FULL   | CF01    |      1 |      8 |      9 |00:00:00.01 |       5 |
|   4 |    INDEX FAST FULL SCAN| CF11_PK |      1 |   1096K|   1096K|00:00:00.04 |    4333 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("B"."ITM_NO"="P"."ITM_NO")
   3 - filter("P"."CTG_NO"=:CTG)

문제 ​

  1. 4번 줄이 무엇을 읽었는지, 상품 9개의 판매 여부를 가리는 데 왜 그만큼이 필요했는지 설명하시오.
  2. 상품마다 판매가 '있는지'만 확인하고 끝나도록 인덱스를 설계하고 SQL을 작성하시오. 하루 2천 번 호출로 따지면 얼마나 줄어드는지와 인덱스를 더하는 대가도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자