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

지난번 단가 소급 MERGE를 기준일만 바꿔 돌렸더니 4월 판매 1만 6천 줄이 5월 단가로 덮였다

중급MERGE유통203 / 700

상황 ​

본사 레거시 유통은 2023년 2분기에 판매가를 두 번 바꿨다. 4월 1일에 상품 30개, 5월 15일에 상품 22개다(12개는 두 번 다 바뀌었다). POS 몇 대가 2분기 내내 옛 단가로 판매를 보내서, 판매상품(CF11)의 판매단가(SLE_UPRC)를 판매일 당시 판매가로 소급해야 한다. 조민우는 지난번 6월 소급 때 쓴 MERGE를 복사해 기간과 기준일('20230515')만 바꿔 돌리고 커밋했다. 다음 날 매장 정산 담당이 "4월에 판 아메리카노가 5월 가격으로 찍혀 있다"라고 알려 왔다. 대조해 보니 고친 23,517행 가운데 16,384행은 맞던 단가를 5월 15일 단가로 덮은 것이었다.

테이블과 인덱스 ​

  • CF10 판매: 500,000행 · 4,583블록 · CF10_PK (SLE_NO) · IX_CF10_SLE_DT (SLE_DT) · 2023년 2분기 판매 62,412건
  • CF11 판매상품: 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO) 높이 3 · SLE_NO는 'YYYYMMDD-NNNN' 모양이고 앞 8자리가 판매일자다(판매 헤더의 SLE_DT와 다른 행 0건) · 2분기 137,214줄(CF11_PK 리프 약 543블록)
  • CF05 상품가격 (점이력): 157행 · 5블록 · CF05_PK (ITM_NO, UPRC_KN_CD, APL_DT) · 판매가(UPRC_KN_CD = '10') 141행 = '20220101' 89행 + '20230401' 30행 + '20230515' 22행 · 나머지는 발주단가
  • 통계 최신

원본 SQL ​

sql
-- 6월 소급 때의 MERGE 에서 기간과 기준일만 바꿨다
MERGE INTO CF11 d
USING (SELECT i.ROWID AS rid, p.ITM_UPRC
         FROM CF10 h
         JOIN CF11 i ON i.SLE_NO = h.SLE_NO
         JOIN (SELECT ITM_NO,
                      MAX(ITM_UPRC) KEEP (DENSE_RANK LAST ORDER BY APL_DT) AS ITM_UPRC
                 FROM CF05
                WHERE UPRC_KN_CD = '10'
                  AND APL_DT <= '20230515'
                GROUP BY ITM_NO) p
           ON p.ITM_NO = i.ITM_NO
        WHERE h.SLE_DT BETWEEN '20230401' AND '20230630') s
   ON (d.ROWID = s.rid)
 WHEN MATCHED THEN UPDATE
      SET d.SLE_UPRC = s.ITM_UPRC
    WHERE DECODE(d.SLE_UPRC, s.ITM_UPRC, 0, 1) = 1

실행계획 학습용 예시 ​

xplan
----------------------------------------------------------------------------------------------------------------
| Id  | Operation                              | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------------
|   0 | MERGE STATEMENT                        |                |      1 |        |      0 |00:00:01.38 |     349K|
|   1 |  MERGE                                 | CF11           |      1 |        |      0 |00:00:01.38 |     349K|
|   2 |   VIEW                                 |                |      1 |        |    137K|00:00:00.71 |     325K|
|   3 |    NESTED LOOPS                        |                |      1 |    137K|    137K|00:00:00.66 |     325K|
|*  4 |     HASH JOIN                          |                |      1 |    137K|    137K|00:00:00.39 |     187K|
|   5 |      VIEW                              |                |      1 |     89 |     89 |00:00:00.01 |       5 |
|   6 |       SORT GROUP BY                    |                |      1 |     89 |     89 |00:00:00.01 |       5 |
|*  7 |        TABLE ACCESS FULL               | CF05           |      1 |    141 |    141 |00:00:00.01 |       5 |
|   8 |      NESTED LOOPS                      |                |      1 |    137K|    137K|00:00:00.31 |     187K|
|   9 |       TABLE ACCESS BY INDEX ROWID BATCHED| CF10         |      1 |  62400 |  62412 |00:00:00.03 |     747 |
|* 10 |        INDEX RANGE SCAN                | IX_CF10_SLE_DT |      1 |  62400 |  62412 |00:00:00.01 |     175 |
|* 11 |       INDEX RANGE SCAN                 | CF11_PK        |  62412 |      2 |    137K|00:00:00.22 |     187K|
|  12 |     TABLE ACCESS BY USER ROWID         | CF11           |    137K|      1 |    137K|00:00:00.21 |     137K|
----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   4 - access("P"."ITM_NO"="I"."ITM_NO")
   7 - filter(("UPRC_KN_CD"='10' AND "APL_DT"<='20230515'))
  10 - access("H"."SLE_DT">='20230401' AND "H"."SLE_DT"<='20230630')
  11 - access("I"."SLE_NO"="H"."SLE_NO")

  갱신된 행 23,517 (그중 16,384행: 4월 1일 ~ 5월 14일 판매인데 5월 15일 단가로 덮였다)

문제 ​

  1. 6월 소급 때는 맞던 MERGE가 이번에는 틀린 까닭을 CF05를 상품마다 한 행으로 줄인 방식으로 설명하시오.
  2. 판매일마다 그날 적용되던 판매가로 맞추는 MERGE를 작성하시오. 이미 잘못 덮인 16,384행은 어떻게 되는지도 쓰시오.
  3. 원천을 만드는 데 판매 헤더(CF10)가 꼭 필요한지 판단하고, 고친 MERGE의 일량을 숫자로 견주시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자