테마
정산팀 「주문 모니터」 개편으로 위젯 셋이 새로 붙었다. 정산팀 PC 30대가 08 ~ 20시에 5분마다 새로 고쳐서 위젯마다 하루 약 4,300번 돈다. 오픈 첫 주에 세 위젯의 SQL이 AWR 논리 읽기 1 ~ 3위를 차지했다. 위젯 설명서는 이렇다. W1 「상태별 최근 주문 10건」(같은 날이면 주문번호 역순), W2 「최근 7일 일자별 고액 주문 TOP 5」(금액이 같으면 공동 순위로 모두 보여 준다), W3 「이번 달 등급별 매출 상위 고객 10명」(공동 순위 포함). 박팀장은 "주문 테이블 인덱스는 지금 둘에서 하나까지만 더할 수 있다. 위젯마다 무엇을 정렬하고 어디서 멈추는지 적어 달라"라고 했다.
T_ORD_BIG: 1,000,000행 · 5,826블록 · ORD_DT 2022-01-01 ~ 2024-12-31(전부 자정, 하루 913건) · ORD_ST COMPLETE 90% · PENDING 8% · CANCEL 2%(NOT NULL, 값은 셋뿐) · ORD_AMT 1만 ~ 50만 원에 고르게 분포 · ORD_SEQ 유일 · 행이 날짜순으로 놓여 있지 않다(날짜 인덱스 CF 약 1,000,000)IX_ORD_BIG_DT_AMT (ORD_DT, ORD_AMT): 「기간 매출」 화면용 · BLEVEL 2 · 리프 3,206블록(리프 한 블록에 약 312항목)IX_ORD_BIG_CUS_DT (CUS_ID, ORD_DT): CS 화면용 · BLEVEL 2 · 리프 약 3,000블록M_CUS: 2,000행 · 30블록 · CUS_GD A 1% · B 9% · C 90% · 이번 달(2024년 12월) 주문은 28,303건 · 통계 최신-- W1 상태별 최근 주문 10건
SELECT ORD_ST, ORD_SEQ, CUS_ID, ORD_DT, ORD_AMT
FROM (SELECT ORD_ST, ORD_SEQ, CUS_ID, ORD_DT, ORD_AMT,
ROW_NUMBER() OVER (PARTITION BY ORD_ST ORDER BY ORD_DT DESC, ORD_SEQ DESC) AS rn
FROM T_ORD_BIG)
WHERE rn <= 10;
-- W2 최근 7일 일자별 고액 주문 TOP 5
SELECT ORD_DT, ORD_SEQ, CUS_ID, ORD_AMT, rn
FROM (SELECT ORD_DT, ORD_SEQ, CUS_ID, ORD_AMT,
ROW_NUMBER() OVER (PARTITION BY ORD_DT ORDER BY ORD_AMT DESC, ORD_SEQ DESC) AS rn
FROM T_ORD_BIG
WHERE ORD_DT >= :d - 6 AND ORD_DT < :d + 1)
WHERE rn <= 5;
-- W3 이번 달 등급별 매출 상위 고객 10명
SELECT CUS_GD, CUS_ID, AMT, rk
FROM (SELECT c.CUS_GD, o.CUS_ID, SUM(o.ORD_AMT) AS AMT,
RANK() OVER (PARTITION BY c.CUS_GD ORDER BY SUM(o.ORD_AMT) DESC) AS rk
FROM T_ORD_BIG o, M_CUS c
WHERE o.ORD_DT >= :m1 AND o.ORD_DT < ADD_MONTHS(:m1, 1)
AND c.CUS_ID = o.CUS_ID
GROUP BY c.CUS_GD, o.CUS_ID)
WHERE rk <= 10;
[W1]
-------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
-------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 30 |00:00:00.43 | 5826 | |
|* 1 | VIEW | | 1 | 1000K| 30 |00:00:00.43 | 5826 | |
|* 2 | WINDOW SORT PUSHED RANK| | 1 | 1000K| 30 |00:00:00.43 | 5826 | 4096 (0)|
| 3 | TABLE ACCESS FULL | T_ORD_BIG | 1 | 1000K| 1000K|00:00:00.06 | 5826 | |
-------------------------------------------------------------------------------------------------------------
1 - filter("RN"<=10)
2 - filter(ROW_NUMBER() OVER ( PARTITION BY "ORD_ST" ORDER BY INTERNAL_FUNCTION("ORD_DT") DESC ,
INTERNAL_FUNCTION("ORD_SEQ") DESC )<=10)
[W2 · :d = 2024-12-31]
-------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
-------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 35 |00:00:00.08 | 5826 | |
|* 1 | VIEW | | 1 | 6391 | 35 |00:00:00.08 | 5826 | |
|* 2 | WINDOW SORT PUSHED RANK| | 1 | 6391 | 35 |00:00:00.08 | 5826 | 2048 (0)|
|* 3 | TABLE ACCESS FULL | T_ORD_BIG | 1 | 6391 | 6391 |00:00:00.06 | 5826 | |
-------------------------------------------------------------------------------------------------------------
1 - filter("RN"<=5)
2 - filter(ROW_NUMBER() OVER ( PARTITION BY "ORD_DT" ORDER BY INTERNAL_FUNCTION("ORD_AMT") DESC ,
INTERNAL_FUNCTION("ORD_SEQ") DESC )<=5)
3 - filter(("ORD_DT">=:D-6 AND "ORD_DT"<:D+1))
[W3 · :m1 = 2024-12-01]
-------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
-------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 30 |00:00:00.19 | 5856 | |
|* 1 | VIEW | | 1 | 2000 | 30 |00:00:00.19 | 5856 | |
|* 2 | WINDOW SORT PUSHED RANK| | 1 | 2000 | 30 |00:00:00.19 | 5856 | 4096 (0)|
| 3 | HASH GROUP BY | | 1 | 2000 | 2000 |00:00:00.19 | 5856 | 1412K (0)|
|* 4 | HASH JOIN | | 1 | 28303 | 28303 |00:00:00.17 | 5856 | 1236K (0)|
| 5 | TABLE ACCESS FULL | M_CUS | 1 | 2000 | 2000 |00:00:00.01 | 30 | |
|* 6 | TABLE ACCESS FULL | T_ORD_BIG | 1 | 28303 | 28303 |00:00:00.15 | 5826 | |
-------------------------------------------------------------------------------------------------------------
1 - filter("RK"<=10)
2 - filter(RANK() OVER ( PARTITION BY "C"."CUS_GD" ORDER BY SUM("O"."ORD_AMT") DESC )<=10)
4 - access("C"."CUS_ID"="O"."CUS_ID")
6 - filter(("O"."ORD_DT">=:M1 AND "O"."ORD_DT"<ADD_MONTHS(:M1,1)))