테마
버거원 본사는 매일 04:00에 매장 POS가 보낸 주문 파일을 ORD_STG에 받아 ORD에 반영한다. 파일에는 새 주문과, 매장이 정정해 다시 보낸 주문(재전송)이 섞여 있다. 지금 배치는 새 주문을 INSERT한 다음, 파일에 있는 주문을 모두 UPDATE한다.
한 달에 두세 번은 POS 재시도로 같은 주문이 한 파일에 두 번 들어와 INSERT가 ORA-00001로 멈춘다. 그러면 아침에 운영 담당이 중복 행을 손으로 지우고 다시 돌린다.
ORD 주문: 1,000,000행 · 22,422블록 · ORD_PK (ORD_NO) 높이 3 · ORD_X01 (ORD_DT, ORD_HMS)ORD_STG(적재용, 날마다 비우고 받는다): 34블록 · ORD_NO, ORD_DT, ORD_HMS, SHOP_NO, RCV_SEQ(수신 순번) · 제약과 인덱스는 없다RCV_SEQ가 큰 쪽)이 맞다. 세 칸(ORD_DT, ORD_HMS, SHOP_NO)은 NOT NULL이다.-- ① 새 주문
INSERT INTO ORD (ORD_NO, ORD_DT, ORD_HMS, SHOP_NO)
SELECT s.ORD_NO, s.ORD_DT, s.ORD_HMS, s.SHOP_NO
FROM ORD_STG s
WHERE NOT EXISTS (SELECT 1 FROM ORD o WHERE o.ORD_NO = s.ORD_NO);
-- ② 정정 (파일에 있는 주문은 모두)
UPDATE ORD o
SET (o.ORD_DT, o.ORD_HMS, o.SHOP_NO) =
(SELECT s.ORD_DT, s.ORD_HMS, s.SHOP_NO FROM ORD_STG s WHERE s.ORD_NO = o.ORD_NO)
WHERE o.ORD_NO IN (SELECT s.ORD_NO FROM ORD_STG s);
COMMIT;
[중복이 없던 어제 · 1,450행 파일 — ① INSERT 위 · ② UPDATE 아래]
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
---------------------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | 1 | | 0 |00:00:00.08 | 10566 |
| 1 | LOAD TABLE CONVENTIONAL | ORD | 1 | | 0 |00:00:00.08 | 10566 |
| 2 | NESTED LOOPS ANTI | | 1 | 1450 | 1371 |00:00:00.01 | 4384 |
| 3 | TABLE ACCESS FULL | ORD_STG | 1 | 1450 | 1450 |00:00:00.01 | 34 |
|* 4 | INDEX UNIQUE SCAN | ORD_PK | 1450 | 1 | 79 |00:00:00.01 | 4350 |
---------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | | 0 |00:00:00.24 | 58075 |
| 1 | UPDATE | ORD | 1 | | 0 |00:00:00.24 | 58075 |
| 2 | NESTED LOOPS | | 1 | 1450 | 1450 |00:00:00.01 | 4384 |
| 3 | SORT UNIQUE | | 1 | 1450 | 1450 |00:00:00.01 | 34 |
| 4 | TABLE ACCESS FULL | ORD_STG | 1 | 1450 | 1450 |00:00:00.01 | 34 |
|* 5 | INDEX UNIQUE SCAN | ORD_PK | 1450 | 1 | 1450 |00:00:00.01 | 4350 |
|* 6 | TABLE ACCESS FULL | ORD_STG | 1450 | 1 | 1450 |00:00:00.05 | 49300 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
① 4 - access("O"."ORD_NO"="S"."ORD_NO")
② 5 - access("O"."ORD_NO"="S"."ORD_NO")
6 - filter("S"."ORD_NO"=:B1)
[중복 2행이 있던 오늘 — ① INSERT]
ORA-00001: unique constraint (DEV.ORD_PK) violated → 문장 전체가 되돌려지고 배치가 멈췄다