Skip to content
튜닝 연습DML과 배치 튜닝
DML-061

리포트를 중간 집계 테이블에서 뽑게 바꾸자 매장 월 주문 수가 원장의 2.5배로 찍힌다

중급INSERT버거486 / 700

상황 ​

버거원 본사 BI팀은 매월 리포트 두 개(매장 월 리포트, 상품 월 리포트)를 원장(ORD와 ORD_ITEM)에서 직접 집계해 왔다. 리포트 하나에 약 3,500블록씩 읽는다. 이번 달부터 매일 밤 다시 계산해 두는 중간 집계 테이블 SHOP_ITEM_MON에서 두 리포트를 뽑게 바꿨고, 리포트 하나가 150블록 남짓으로 줄었다. 12월 리포트를 받은 영업팀이 물었다. "매장 주문 수가 왜 작년보다 두 배 넘게 늘었죠? 주문당 수량은 1.4개로 떨어졌고요." 상품 월 리포트의 상품별 주문 수는 원장과 맞는다.

테이블과 인덱스 ​

  • ORD 주문: 1,000,000행 · 22,422블록 · 날짜순 적재 · ORD_X01 (ORD_DT, ORD_HMS) · 2013년 12월 42,408건 · SHOP_NO 200개
  • ORD_ITEM 주문상품: 2,472,717행 · 55,265블록 · ORD_ITEM_PK (ORD_NO, ITEM_ID)(주문 하나에 같은 상품은 한 줄) · 12월 106,342행 · 12월 판매 수량 합계 148,879개
  • SHOP_ITEM_MON(중간 집계, 이 문제용): PK SHOP_ITEM_MON_PK (ORD_YM, SHOP_NO, ITEM_ID) · SALE_QTY(수량 합) · LINE_CNT(주문상품 줄 수) · ORD_CNT(그 매장에서 그 상품이 들어간 주문 수, COUNT(DISTINCT ORD_NO)) · 매일 밤 그 달 분을 다시 계산한다 · 12월 17,934행
  • RPT_SHOP_MON, RPT_ITEM_MON(리포트, 이 문제용): 매달 그 달 행을 지우고 다시 넣는다. 통계는 최신이다.

원본 SQL ​

sql
-- 이번 달부터: 리포트 둘을 중간 집계 SHOP_ITEM_MON 에서 만든다
INSERT INTO RPT_SHOP_MON (ORD_YM, SHOP_NO, ORD_CNT, SALE_QTY, QTY_PER_ORD)
SELECT ORD_YM, SHOP_NO, SUM(ORD_CNT), SUM(SALE_QTY), ROUND(SUM(SALE_QTY) / SUM(ORD_CNT), 2)
  FROM SHOP_ITEM_MON
 WHERE ORD_YM = :ym
 GROUP BY ORD_YM, SHOP_NO;

INSERT INTO RPT_ITEM_MON (ORD_YM, ITEM_ID, ORD_CNT, SALE_QTY)
SELECT ORD_YM, ITEM_ID, SUM(ORD_CNT), SUM(SALE_QTY)
  FROM SHOP_ITEM_MON
 WHERE ORD_YM = :ym
 GROUP BY ORD_YM, ITEM_ID;

실행계획 학습용 예시 ​

xplan
[매장 월 리포트 — 12월]
----------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name             | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT                     |                  |      1 |        |      0 |00:00:00.03 |     151 |
|   1 |  LOAD TABLE CONVENTIONAL             | RPT_SHOP_MON     |      1 |        |      0 |00:00:00.03 |     151 |
|   2 |   HASH GROUP BY                      |                  |      1 |    200 |    200 |00:00:00.02 |     138 |
|   3 |    TABLE ACCESS BY INDEX ROWID BATCHED| SHOP_ITEM_MON   |      1 |  17934 |  17934 |00:00:00.01 |     138 |
|*  4 |     INDEX RANGE SCAN                 | SHOP_ITEM_MON_PK |      1 |  17934 |  17934 |00:00:00.01 |      58 |
----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   4 - access("ORD_YM"=:YM)

[12월 대조 — 원장 직접 집계와 두 리포트]
                            원장(직접 집계)   RPT_SHOP_MON   RPT_ITEM_MON
  주문 수 합계                     42,408        106,342        106,342 (상품별 주문 수를 모두 더한 값)
  상품 I0007 주문 수                9,815              —          9,815
  매장 SH0001 주문 수                 207            519              —
  판매 수량 합계                  148,879        148,879        148,879
  주문당 수량                        3.51           1.40              —

문제 ​

  1. 매장 월 리포트의 주문 수가 원장의 약 2.5배로 나온 이유를 설명하시오. 같은 SUM(ORD_CNT)인데 상품 월 리포트의 상품별 주문 수는 왜 맞는지도 쓰시오.
  2. 중간 집계를 읽는 이점은 살리면서 매장 월 리포트를 바로잡으시오. 중간 집계 테이블에 둘 수 있는 값과 그대로 더하면 안 되는 값을 가르는 기준도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자