테마
매월 1일 03:00 마감 배치는 지난달 주문을 정산 확정으로 바꾼다(STLM_YN을 'N'에서 'Y'로). 정산팀의 「미정산 주문 현황」은 정산 담당 열 명이 수시로 열어 하루 약 300번 실행되는데, 매번 테이블을 통째로 읽어서 6월에 조민우가 (STLM_YN, ORD_DT, ORD_AMT) 인덱스를 만들었다. 화면은 5,826블록에서 50블록 안팎으로 줄었다.
그런데 7월 1일 마감에서 확정 UPDATE의 redo가 9.6MB에서 24.3MB로, 시간이 1.3초에서 3.4초로 늘었다. 배치 담당 오과장이 물었다. "바꾸는 건 지난달처럼 2만 7천 건 남짓인데 왜 두 배 반이냐?"
T_ORD_BIG: 1,000,000행 · 5,826블록 · 이 문제에서는 STLM_YN CHAR(1)(정산 여부) 컬럼이 있다고 둔다 · 새 주문은 'N'으로 들어오고, 마감 배치가 지난달 주문을 한꺼번에 'Y'로 바꾼다 · 그래서 'N'인 행은 늘 그달 치(최대 약 2만 8천 건)다IX_ORD_BIG_DT_AMT (ORD_DT, ORD_AMT): 「기간 매출」용 · IX_ORD_BIG_YN_DT_AMT (STLM_YN, ORD_DT, ORD_AMT): 6월에 새로 만들었다 · BLEVEL 2 · 리프 약 3,520블록(리프 한 블록에 약 284항목) · 통계 최신-- 매월 1일 03:00 · 정산 확정 (지난달 주문)
UPDATE T_ORD_BIG
SET STLM_YN = 'Y'
WHERE ORD_DT >= ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -1)
AND ORD_DT < TRUNC(SYSDATE, 'MM')
AND STLM_YN = 'N';
-- 「미정산 주문 현황」 · 하루 약 300번
SELECT ORD_DT, COUNT(*) AS cnt, SUM(ORD_AMT) AS amt
FROM T_ORD_BIG
WHERE STLM_YN = 'N'
GROUP BY ORD_DT
ORDER BY ORD_DT;
[정산 확정 UPDATE · 세션 통계]
6월 1일 (5월분, 인덱스 전) 7월 1일 (6월분, 인덱스 뒤)
바뀐 행 28,303 27,390
경과 1.3초 3.4초
redo size 9.6 MB 24.3 MB
db block changes 57,148 168,931
session logical reads 64,410 251,302
[7월 1일 · 정산 확정 UPDATE]
----------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | | 0 |00:00:03.38 | 251K |
| 1 | UPDATE | T_ORD_BIG | 1 | | 0 |00:00:03.38 | 251K |
|* 2 | TABLE ACCESS FULL| T_ORD_BIG | 1 | 27390 | 27390 |00:00:00.06 | 5826 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(("STLM_YN"='N' AND "ORD_DT">=ADD_MONTHS(TRUNC(SYSDATE@!,'fmmm'),-1) AND
"ORD_DT"<TRUNC(SYSDATE@!,'fmmm')))
(6월 1일에도 같은 모양이었다 · 1번 줄 Buffers 64K)
[「미정산 주문 현황」 7월 15일 · 인덱스 뒤]
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 15 |00:00:00.01 | 51 |
| 1 | SORT GROUP BY NOSORT| | 1 | 31 | 15 |00:00:00.01 | 51 |
|* 2 | INDEX RANGE SCAN | IX_ORD_BIG_YN_DT_AMT | 1 | 14000 | 13695 |00:00:00.01 | 51 |
-----------------------------------------------------------------------------------------------------
2 - access("STLM_YN"='N')
(인덱스 전에는 TABLE ACCESS FULL · Buffers 5,826)