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

해시 조인 힌트를 넣었다는 월 정산 대사가 여전히 주문을 4,170번 찾아간다

기초SELECT한빛유통226 / 700

상황 ​

정산팀의 「월 정산 대사」는 한 달 치 정산마다 주문을 붙여 정산 금액이나 고객이 주문과 다른 건을 찾는다. 2019년에 「일 정산 대사」로 만들 때 오과장이 힌트를 달았고, 올해 5월에 화면이 한 달 단위로 바뀌었다. 조민우는 한 달이면 해시가 맞다고 보고 힌트를 고쳤다. 팀 규칙이 "옛 힌트는 지우지 말고 바로 아래에 새 힌트를 덧붙여 이력을 남긴다"여서 그대로 따랐다. 그런데 계획은 여전히 NL이다. 조민우는 "힌트를 무시하는 버그 아니냐"라고 묻는다. 아래는 2024년 6월로 돌린 실행계획이다.

테이블과 인덱스 ​

  • T_ORD_STLM 정산: 100,000행 · 640블록 · 인덱스 없음 · 2024년 6월 정산 4,170행
  • T_ORD 주문: 100,000행 · 896블록 · PK_T_ORD (ORD_SEQ) (BLEVEL 1)
  • 정산과 주문은 ORD_SEQ로 1:1이다 · 통계 최신

원본 SQL ​

sql
SELECT /*+ LEADING(s o) USE_NL(o) */            -- 2019.03 일 대사 (오과장)
       /*+ LEADING(s o) USE_HASH(o) FULL(o) */  -- 2024.05 월 대사로 바뀌어 해시로 (조민우)
       s.STLM_SEQ, s.ORD_SEQ, s.STLM_DT, s.STLM_AMT, o.ORD_AMT, o.PAY_AMT
  FROM T_ORD_STLM s, T_ORD o
 WHERE s.STLM_DT >= TO_DATE(:v_ym || '01', 'YYYYMMDD')
   AND s.STLM_DT <  ADD_MONTHS(TO_DATE(:v_ym || '01', 'YYYYMMDD'), 1)
   AND o.ORD_SEQ = s.ORD_SEQ
   AND (o.ORD_AMT <> s.STLM_AMT OR o.CUS_ID <> s.CUS_ID)

실행계획 학습용 예시 ​

xplan
--------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |            |      1 |        |      3 |00:00:00.04 |   13149 |
|   1 |  NESTED LOOPS                |            |      1 |   4170 |      3 |00:00:00.04 |   13149 |
|   2 |   NESTED LOOPS               |            |      1 |   4170 |   4170 |00:00:00.02 |    8979 |
|*  3 |    TABLE ACCESS FULL         | T_ORD_STLM |      1 |   4170 |   4170 |00:00:00.01 |     640 |
|*  4 |    INDEX UNIQUE SCAN         | PK_T_ORD   |   4170 |      1 |   4170 |00:00:00.01 |    8339 |
|*  5 |   TABLE ACCESS BY INDEX ROWID| T_ORD      |   4170 |      1 |      3 |00:00:00.02 |    4170 |
--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   3 - filter(("S"."STLM_DT">=TO_DATE(:V_YM||'01','YYYYMMDD') AND
              "S"."STLM_DT"<ADD_MONTHS(TO_DATE(:V_YM||'01','YYYYMMDD'),1)))
   4 - access("O"."ORD_SEQ"="S"."ORD_SEQ")
   5 - filter(("O"."ORD_AMT"<>"S"."STLM_AMT" OR "O"."CUS_ID"<>"S"."CUS_ID"))

Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 2
---------------------------------------------------------------------------

   1 -  SEL$1
         -  LEADING(s o)

   4 -  SEL$1 / "O"@"SEL$1"
         -  USE_NL(o)

문제 ​

  1. 새 힌트가 계획에 반영되지 않은 이유를 Hint Report로 설명하시오. 지금 계획이 4번과 5번 줄에서 하는 일을 Starts로 쓰시오.
  2. 월 대사에 맞게 SQL을 고치고, 바뀐 판단을 어디에 어떻게 기록할지 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자