테마
경영지원팀 대시보드의 「월 매출 전년 대비」는 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_AMTSELECT 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
-----------------------------------------------------------------------------------------------------------------------------------
| 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 | | |
-----------------------------------------------------------------------------------------------------------------------------------
LAG(…, 12)로 구할 때 데이터가 지켜야 할 조건도 쓰시오.