테마
본사 레거시 유통은 매장 판매를 1분마다 본사 사본 테이블 HQ_SLE로 옮겨 실시간 매출판에 띄운다. 지난달 매장 POS의 판매번호 받기를 고친 뒤부터, 매출판의 하루 합계가 마감 정산보다 늘 2 ~ 5건 적다. 빠진 판매는 다음 날에도 매출판에 나타나지 않는다.
지난달의 변경은 이렇다. 결제 저장 때 번호를 받느라 다른 매장의 저장을 기다린다는 민원이 있어서, 번호를 받는 시점을 결제 저장에서 첫 상품 스캔으로 앞당기고 채번 행은 자율 트랜잭션으로 바로 COMMIT하게 했다. 판매 행(CF10, CF11)은 결제가 끝나야 INSERT하고 COMMIT한다.
본사 전산 담당자는 이렇게 제안했다. "판매번호를 시퀀스로 바꾸고 ORDER를 붙이면 순서가 맞지 않을까요?"
CF10 판매: 500,000행 · 4,583블록 · CF10_PK (SLE_NO) · SLE_NO 날짜 여덟 자리와 하이픈, 그날의 네 자리 일련번호 · 하루 약 700건SLE_HMS는 결제 시각이다. 결제 저장의 INSERT가 DB의 SYSDATE로 적고, 바로 COMMIT한다CF11 판매상품: 1,096,708행 · CF11_PK (SLE_NO, ITM_NO) · 판매당 약 2.2행CF10_NUM 판매번호 채번 행(지난달에 만들었다): PK (SLE_DT) · 번호는 자율 트랜잭션으로 받고 바로 COMMIT한다HQ_SLE 본사 사본(이 문제를 위해 더한 테이블): PK (SLE_NO) · SLE_DT · SHP_NO · SLE_AMT-- 1분마다 — 지난번에 옮긴 마지막 판매번호 뒤부터 옮긴다
INSERT INTO HQ_SLE (SLE_NO, SLE_DT, SHP_NO, SLE_AMT)
SELECT h.SLE_NO, h.SLE_DT, h.SHP_NO, SUM(d.SLE_QTY * d.SLE_UPRC)
FROM CF10 h
JOIN CF11 d ON d.SLE_NO = h.SLE_NO
WHERE h.SLE_NO > :last_sle_no
GROUP BY h.SLE_NO, h.SLE_DT, h.SHP_NO;
SELECT MAX(SLE_NO) INTO :last_sle_no FROM HQ_SLE; -- 다음 번의 시작점
COMMIT;
[시간표 — 2023-12-16(토)]
시각 매장 1002 POS (SID 41) 매장 1004 POS (SID 58) 1분 추출 (SID 90)
10:00:05 첫 스캔 → 번호 20231216-0412 (자율 COMMIT)
10:00:20 첫 스캔 → 번호 0413 (자율 COMMIT)
10:00:41 결제 · CF10 · CF11 INSERT · COMMIT
10:01:00 SLE_NO > '…-0411' → 0413 을 옮긴다
(0412 는 COMMIT 전이라 안 보인다)
다음 시작점 '…-0413'
10:01:12 결제 · CF10 · CF11 INSERT · COMMIT
10:02:00 SLE_NO > '…-0413' → 0412 는 범위 밖
[12월 둘째 주 · 하루 대사]
날짜 마감 정산 판매 HQ_SLE 빠진 판매번호
12/11(월) 684 681 0233 · 0571 · 0602
12/16(토) 731 726 0412 · 0498 · 0517 · 0603 · 0688
빠진 판매는 모두 번호를 받고 나서 다음 번호보다 늦게 COMMIT 한 판매다
[추출 한 번 — ALLSTATS LAST · 10:01:00]
------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | 1 | | 0 |00:00:00.01 | 21 |
| 1 | LOAD TABLE CONVENTIONAL | HQ_SLE | 1 | | 0 |00:00:00.01 | 21 |
| 2 | HASH GROUP BY | | 1 | 1 | 1 |00:00:00.01 | 12 |
| 3 | NESTED LOOPS | | 1 | 2 | 2 |00:00:00.01 | 12 |
| 4 | TABLE ACCESS BY INDEX ROWID| CF10 | 1 | 1 | 1 |00:00:00.01 | 4 |
|* 5 | INDEX RANGE SCAN | CF10_PK | 1 | 1 | 1 |00:00:00.01 | 3 |
| 6 | TABLE ACCESS BY INDEX ROWID| CF11 | 1 | 2 | 2 |00:00:00.01 | 8 |
|* 7 | INDEX RANGE SCAN | CF11_PK | 1 | 2 | 2 |00:00:00.01 | 3 |
------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("H"."SLE_NO">:LAST_SLE_NO)
7 - access("D"."SLE_NO"="H"."SLE_NO")