테마
POS 중계 서버 장애로 12월 23일 ~ 29일 일주일 치 주문이 본사에 들어오지 않다가, 12월 30일 03:10에 업체가 한꺼번에 다시 보내 ORD와 ORD_ITEM에 다 들어갔다. 일 마감 체인은 기준일 하루를 처리하도록 짜여 있고 평소에는 04:00에 전날분을 한 번 돈다. 05:00에 매장 발주 자동 생성이 최근 7일의 매장 일 집계와 메뉴 순위를 읽으므로 그 전에 일곱 날을 모두 마감해야 한다. 03:30부터 시작할 수 있다.
당직 개발자는 기준일만 바꿔 체인을 일곱 번 돌리겠다고 한다. 오과장: "한 번 도는 데 15분 30초니까 108분이 넘어요. 날짜 범위로 한 번에 돌리면 안 되나요?" 개발자: "WHERE만 범위로 바꾸면 되긴 하는데요…"
ORD 1,000,000행 · 22,422블록 · ORD_X01 (ORD_DT, ORD_HMS) · ORD_ITEM 2,472,717행 · 55,265블록 · ORD_ITEM_X01 (ORD_DT, ORD_HMS) · 12/23 ~ 12/29 주문 9,604건, 주문상품 24,017행(테이블의 약 1%)SHOP_DAY(매장 일 집계) · SHOP_ITEM_RANK(매장 메뉴 일 순위, 매장마다 날마다 상위 10개) · ITEM_MON(메뉴 월 누계): 모두 이 문제용이며 기준일 단위로 지우고 다시 넣거나 다시 계산해 덮는다(다시 돌려도 같다).P_ITEM_MON_REBUILD(ym): 그 달 1일부터 지금까지를 ORD_ITEM에서 다시 합산해 덮는다. P_RPT_CACHE_REBUILD: 최근 13개월 매장 × 메뉴 × 월 요약을 통째로 다시 만든다. P_DW_DAY_FILE(d): DW가 기다리는 '기준일 하루 = 파일 하나'를 만들어 보낸다.ORD_ITEM 한 번에 약 17초).PROCEDURE P_DAY_CLOSE(p_d VARCHAR2) IS -- 매일 04:00 · p_d = 전날 'YYYYMMDD'
BEGIN
-- S1 매장 일 집계
DELETE FROM SHOP_DAY WHERE ORD_DT = p_d;
INSERT INTO SHOP_DAY (ORD_DT, SHOP_NO, ORD_CNT, SALE_QTY)
SELECT o.ORD_DT, o.SHOP_NO, COUNT(DISTINCT o.ORD_NO), SUM(i.ORD_ITEM_QTY)
FROM ORD o, ORD_ITEM i
WHERE o.ORD_DT = p_d AND i.ORD_DT = p_d AND i.ORD_NO = o.ORD_NO
GROUP BY o.ORD_DT, o.SHOP_NO;
COMMIT;
-- S2 매장 메뉴 일 순위 (매장마다 상위 10개)
DELETE FROM SHOP_ITEM_RANK WHERE ORD_DT = p_d;
INSERT INTO SHOP_ITEM_RANK (ORD_DT, SHOP_NO, ITEM_ID, SALE_QTY, RNK)
SELECT p_d, SHOP_NO, ITEM_ID, QTY, RNK
FROM (SELECT o.SHOP_NO, i.ITEM_ID, SUM(i.ORD_ITEM_QTY) AS QTY,
ROW_NUMBER() OVER (PARTITION BY o.SHOP_NO
ORDER BY SUM(i.ORD_ITEM_QTY) DESC, i.ITEM_ID) AS RNK
FROM ORD o, ORD_ITEM i
WHERE o.ORD_DT = p_d AND i.ORD_DT = p_d AND i.ORD_NO = o.ORD_NO
GROUP BY o.SHOP_NO, i.ITEM_ID)
WHERE RNK <= 10;
COMMIT;
P_ITEM_MON_REBUILD(SUBSTR(p_d, 1, 6)); -- S3 메뉴 월 누계
DBMS_STATS.GATHER_TABLE_STATS(USER, 'ORD', estimate_percent => 100); -- S4 통계 수집
DBMS_STATS.GATHER_TABLE_STATS(USER, 'ORD_ITEM', estimate_percent => 100);
P_RPT_CACHE_REBUILD; -- S5 본사 리포트 캐시
P_DW_DAY_FILE(p_d); -- S6 DW 일 파일
END;
[12월 22일 평소 실행 — 단계별]
단계 경과 하는 일 읽는 양
S1 매장 일 집계 0분 06초 그날 주문 · 주문상품 (인덱스 범위) 약 4,600블록
S2 매장 메뉴 일 순위 0분 04초 그날 주문 · 주문상품 (인덱스 범위) 약 4,600블록
S3 메뉴 월 누계 1분 50초 그 달 1일 ~ 그날 ORD_ITEM 전체 스캔 · 해시 집계 55,265블록
S4 통계 수집 6분 40초 ORD · ORD_ITEM 전체 · 100% 표본 77,687블록 + 정렬
S5 본사 리포트 캐시 5분 10초 13개월 ORD · ORD_ITEM 전체 스캔 · TEMP 사용 77,687블록
S6 DW 일 파일 1분 40초 그날 집계로 파일 생성 0분 40초 + 전송 연결 1분
합계 15분 30초
[리허설 — S1, S2의 WHERE만 7일 범위로 바꿔 한 번 돌려 봄]
S1 0분 26초 · SHOP_DAY 1,400행 (200매장 × 7일) — 날마다 돌린 결과와 같다
S2 0분 24초 · SHOP_ITEM_RANK 2,000행 (200매장 × 10개) — 날마다 돌리면 14,000행이어야 한다