Skip to content
튜닝 연습조인 튜닝
JOIN-005

월말 품목 마감표가 109줄이어야 하는데 88줄만 나온다

중급SELECT유통155 / 700

상황 ​

월말 「품목 마감표」는 상품 마스터의 품목마다 한 줄씩 그달 판매 수량과 판매 줄 수를 낸다(판매가 없으면 0). 회계팀은 이 표를 마스터 행 수(109)와 대사하는데, 12월 마감표가 88줄이라 반려했다. 개발자는 "외부 조인 (+)를 붙였으니 다 나와야 한다. 마스터에 21개가 잘못 들어간 것 아닌가?"라고 한다.

테이블과 인덱스 ​

  • CF01 상품: 109행 · 5블록 · CF01_PK (ITM_NO) · 판매상품 88 · 추가상품 1 (샷추가) · 원재료 20
  • CF11 판매상품: 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO) · SLE_NO는 'YYYYMMDD-NNNN' (앞 8자리가 판매일자) · 2023년 12월 46,322줄 · 그달 팔린 품목 88개
  • 원재료 20개와 샷추가는 판매 상세에 한 번도 나오지 않는다 · FK 없음 · 통계 최신
  • 바인드 :v_from = '20231201' · :v_to = '20240101'

원본 SQL ​

sql
SELECT p.ITM_NO, p.ITM_NM,
       NVL(SUM(i.SLE_QTY), 0) AS sle_qty,
       COUNT(i.SLE_NO)        AS sle_lines
  FROM CF01 p, CF11 i
 WHERE i.ITM_NO(+) = p.ITM_NO
   AND i.SLE_NO >= :v_from
   AND i.SLE_NO <  :v_to
 GROUP BY p.ITM_NO, p.ITM_NM
 ORDER BY p.ITM_NO

실행계획 학습용 예시 · 행 수는 실데이터 ​

xplan
--------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |         |      1 |        |     88 |00:00:00.04 |     899 |
|   1 |  SORT GROUP BY                |         |      1 |    109 |     88 |00:00:00.04 |     899 |
|*  2 |   HASH JOIN                   |         |      1 |  45980 |  46322 |00:00:00.03 |     899 |
|   3 |    TABLE ACCESS FULL          | CF01    |      1 |    109 |    109 |00:00:00.01 |       5 |
|   4 |    TABLE ACCESS BY INDEX ROWID| CF11    |      1 |  45980 |  46322 |00:00:00.02 |     894 |
|*  5 |     INDEX RANGE SCAN          | CF11_PK |      1 |  45980 |  46322 |00:00:00.01 |     181 |
--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("I"."ITM_NO"="P"."ITM_NO")
   5 - access("I"."SLE_NO">=:V_FROM AND "I"."SLE_NO"<:V_TO)

문제 ​

  1. 계획 2번 줄에서 무엇이 빠졌는지 찾고, (+)를 붙였는데도 21개 품목이 사라진 이유를 설명하시오.
  2. 109줄이 나오도록 SQL을 고치시오((+) 표기와 ANSI 표기 중 하나 이상). 고친 뒤 성능이 어떻게 되는지, 흔히 쓰는 다른 고침(OR … IS NULL)이 왜 틀렸는지도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자