Skip to content
튜닝 연습소트 튜닝과 페이징
SORT-054

「월 매출 전년 대비」 36줄을 내는 데 TEMP를 31MB 쓴다

중급SELECT한빛유통359 / 700

상황 ​

경영지원팀 대시보드의 「월 매출 전년 대비」는 3년 치 주문을 달별로 더해 주문 수와 금액, 전년 같은 달 대비 증감률을 보여 준다. 임원 회의 자료와 팀장들의 대시보드에서 하루 약 200번 열린다. 한 번 여는 데 1.6초가 걸리고, DBA의 TEMP 사용 보고에 매일 이 SQL이 오른다. 개발자는 "GROUP BY를 하면 LAG를 못 쓸 것 같아서, 달별 합계를 분석 함수로 구하고 DISTINCT로 한 줄씩 남겼다"라고 한다.

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 5,826블록 · ORD_DT 2022-01-01 ~ 2024-12-31(36개월, 빠진 달 없음) · ORD_AMT
  • 3년 치 전체를 읽으므로 인덱스는 쓰지 않는다. 운영 PGA는 자동 관리이고, 이 시간대에는 다른 리포트도 함께 돈다.
  • 통계는 최신이다.

원본 SQL ​

sql
SELECT ym, ord_cnt, ord_amt,
       LAG(ord_amt, 12) OVER (ORDER BY ym) AS prev_amt,
       ROUND((ord_amt - LAG(ord_amt, 12) OVER (ORDER BY ym)) * 100
             / LAG(ord_amt, 12) OVER (ORDER BY ym), 1) AS yoy_pct
  FROM (SELECT DISTINCT
               TO_CHAR(ORD_DT, 'YYYYMM') AS ym,
               COUNT(*)     OVER (PARTITION BY TO_CHAR(ORD_DT, 'YYYYMM')) AS ord_cnt,
               SUM(ORD_AMT) OVER (PARTITION BY TO_CHAR(ORD_DT, 'YYYYMM')) AS ord_amt
          FROM T_ORD_BIG)
 ORDER BY ym

실행계획 학습용 예시 ​

xplan
-----------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads | Writes | Used-Mem | Used-Tmp |
-----------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |           |      1 |        |     36 |00:00:01.62 |    5826 |  3890 |   3890 |          |          |
|   1 |  WINDOW SORT          |           |      1 |   1000K|     36 |00:00:01.62 |    5826 |  3890 |   3890 | 2048 (0) |          |
|   2 |   VIEW                |           |      1 |   1000K|     36 |00:00:01.62 |    5826 |  3890 |   3890 |          |          |
|   3 |    HASH UNIQUE        |           |      1 |   1000K|     36 |00:00:01.61 |    5826 |  3890 |   3890 | 1155K (0)|          |
|   4 |     WINDOW SORT       |           |      1 |   1000K|   1000K|00:00:01.38 |    5826 |  3890 |   3890 | 2190K (1)|      31M |
|   5 |      TABLE ACCESS FULL| T_ORD_BIG |      1 |   1000K|   1000K|00:00:00.05 |    5826 |     0 |      0 |          |          |
-----------------------------------------------------------------------------------------------------------------------------------

문제 ​

  1. 36줄을 내는 데 무엇을 몇 행 정렬하는지, TEMP는 어느 줄에서 왜 쓰는지 설명하시오.
  2. 결과가 바뀌지 않게 SQL을 고치시오. 전년 같은 달을 LAG(…, 12)로 구할 때 데이터가 지켜야 할 조건도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자