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

1분마다 새로 고치는 경영 대시보드가 주문 3년 치를 고객 마스터에 다시 맞대 본다

실전SELECT한빛유통181 / 700

상황 ​

경영지원팀 대시보드의 「지역 · 등급 · 월 매출」 칸은 3년 치 주문을 지역, 등급, 월로 묶어 864칸짜리 표를 그린다. 07시부터 19시까지 1분마다 새로 고쳐 하루 720번 돈다. AWR의 CPU 상위 SQL 1위이고, DB CPU의 18%를 차지한다. 해시 조인이라 Buffers는 이미 5,860으로 작다. 박팀장은 "더 줄일 수 있는 안을 모두 모아 숫자와 대가를 붙여 가져오라"라고 했다. 대시보드는 어제까지의 주문만 보여 주면 된다. 주문은 낮 동안 계속 들어오고(하루 약 900건), 지난 주문의 금액 정정이 하루 수십 건 있다.

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 5,826블록 · 인덱스 없음 · 주문일은 2022-01-01부터 어제까지
  • M_CUS: 2,000행 · 30블록 · PK_M_CUS (CUS_ID) · 지역 8곳에 250명씩 · CUS_GD A · B · C
  • M_RGN: 8행 · 4블록 · PK_M_RGN (RGN_ID)
  • 통계 최신 · 아래 CPU는 같은 조건으로 10번 돌려 잰 CPU used by this session의 한 번 평균

원본 SQL ​

sql
SELECT TO_CHAR(o.ORD_DT, 'YYYYMM') AS ym, r.RGN_NM, c.CUS_GD,
       COUNT(*) AS ord_cnt, SUM(o.ORD_AMT) AS ord_amt
  FROM T_ORD_BIG o, M_CUS c, M_RGN r
 WHERE c.CUS_ID = o.CUS_ID
   AND r.RGN_ID = c.RGN_ID
   AND o.ORD_DT < TRUNC(SYSDATE)
 GROUP BY TO_CHAR(o.ORD_DT, 'YYYYMM'), r.RGN_NM, c.CUS_GD

실행계획 학습용 예시 · CPU 비율은 교재 18화 Q2 rev02 실측을 참고 ​

xplan
---------------------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
---------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |           |      1 |        |    864 |00:00:00.82 |    5860 |       |       |          |
|   1 |  HASH GROUP BY         |           |      1 |    864 |    864 |00:00:00.82 |    5860 |  1394K|  1394K| 1408K (0)|
|*  2 |   HASH JOIN            |           |      1 |   1000K|   1000K|00:00:00.58 |    5860 |  1572K|  1572K| 1702K (0)|
|*  3 |    HASH JOIN           |           |      1 |   2000 |   2000 |00:00:00.01 |      34 |  1376K|  1376K|  950K (0)|
|   4 |     TABLE ACCESS FULL  | M_RGN     |      1 |      8 |      8 |00:00:00.01 |       4 |       |       |          |
|   5 |     TABLE ACCESS FULL  | M_CUS     |      1 |   2000 |   2000 |00:00:00.01 |      30 |       |       |          |
|*  6 |    TABLE ACCESS FULL   | T_ORD_BIG |      1 |   1000K|   1000K|00:00:00.06 |    5826 |       |       |          |
---------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("C"."CUS_ID"="O"."CUS_ID")
   3 - access("R"."RGN_ID"="C"."RGN_ID")
   6 - filter("O"."ORD_DT"<TRUNC(SYSDATE@!))

[한 번 실행]  CPU used by this session 41 cs · 하루 720번이면 Buffers 약 422만 · CPU 약 295초

문제 ​

  1. 이 SQL의 일량을 Buffers와 조인에 대는 행 수, CPU로 나눠 설명하시오. 하루 단위의 일량도 계산하시오.
  2. ① 조인 전에 고객과 월로 먼저 묶기 ② 커버링 인덱스 (CUS_ID, ORD_DT, ORD_AMT) ③ 결과 캐시(RESULT_CACHE 힌트) ④ 밤에 한 번 결과를 만들어 두는 요약 테이블, 네 안을 블록과 CPU, 대가로 비교하시오.
  3. 권하는 안을 SQL(DDL 포함)로 작성하고, 지난 주문의 정정을 어떻게 반영하며 정합성을 어떻게 확인할지 서술하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자