테마
매년 1월 첫 일요일에 지난해 주문을 보관 테이블로 옮기는 배치가 돈다. 주문(T_ORD_ARC)을 먼저 옮기고 주문상세(T_ORD_DET_ARC)를 옮긴다. 오과장이 두 INSERT에 모두 /*+ APPEND */를 붙였는데, 주문상세 단계의 redo와 시간은 그대로였다.
리허설에서 실행계획의 Note를 보고 보관 일시를 채우던 트리거를 꺼 봤더니 계획은 여전히 그대로였고, 그렇게 들어간 행은 ARC_DT가 NULL이었다.
T_ORD: 100,000행 · 896블록 · ORD_DT 2023-01-01 ~ 2024-12-31 · 2023년 주문 50,060건 · PK_T_ORD (ORD_SEQ)T_ORD_DET: 200,000행 · 896블록(전체 스캔 807) · 2023년 주문의 상세 100,140행 · PK_T_ORD_DET (ORD_SEQ, ORD_DET_NO)T_ORD_ARC · T_ORD_DET_ARC 보관 테이블(문제 설정): 원본 컬럼에 ARC_DT DATE와 ARC_USER VARCHAR2(30)를 더했다. 처음 보관하는 해라 둘 다 비어 있다. T_ORD_ARC에는 PK_T_ORD_ARC (ORD_SEQ)만 있다.T_ORD_DET_ARC에는 PK_T_ORD_DET_ARC (ORD_SEQ, ORD_DET_NO)와 FK_ORD_DET_ARC (ORD_SEQ) REFERENCES T_ORD_ARC가 있고, 행 트리거 TRG_ORD_DET_ARC_BI(BEFORE INSERT FOR EACH ROW)가 :NEW.ARC_DT := SYSDATE; :NEW.ARC_USER := USER;를 채운다.-- 매년 1월 첫 일요일 · 지난해 주문 보관
-- ① 주문
INSERT /*+ APPEND */ INTO T_ORD_ARC
SELECT o.*, SYSDATE, USER
FROM T_ORD o
WHERE o.ORD_DT >= DATE '2023-01-01' AND o.ORD_DT < DATE '2024-01-01';
COMMIT;
-- ② 주문상세 (ARC_DT · ARC_USER 는 트리거가 채운다)
INSERT /*+ APPEND */ INTO T_ORD_DET_ARC (ORD_SEQ, ORD_DET_NO, ITM_ID, ORD_QTY, UNT_PRC)
SELECT d.ORD_SEQ, d.ORD_DET_NO, d.ITM_ID, d.ORD_QTY, d.UNT_PRC
FROM T_ORD_DET d
WHERE d.ORD_SEQ IN (SELECT ORD_SEQ FROM T_ORD_ARC);
COMMIT;
[② 주문상세 보관 — 리허설 1회차]
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-----------------------------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | 1 | | 0 |00:00:05.87 | 623K |
| 1 | LOAD TABLE CONVENTIONAL | T_ORD_DET_ARC | 1 | | 0 |00:00:05.87 | 623K |
|* 2 | HASH JOIN RIGHT SEMI | | 1 | 100K| 100K|00:00:00.12 | 919 |
| 3 | INDEX FAST FULL SCAN | PK_T_ORD_ARC | 1 | 50060 | 50060 |00:00:00.01 | 112 |
| 4 | TABLE ACCESS FULL | T_ORD_DET | 1 | 200K| 200K|00:00:00.03 | 807 |
-----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("D"."ORD_SEQ"="ORD_SEQ")
Note
-----
- Direct Load disabled because triggers are defined
[② 같은 문장 — 리허설 2회차 · ALTER TRIGGER TRG_ORD_DET_ARC_BI DISABLE 뒤]
1번 줄 LOAD TABLE CONVENTIONAL T_ORD_DET_ARC · A-Time 00:00:03.62 · Buffers 512K (아래 줄은 1회차와 같다)
Note
-----
- Direct Load disabled because parent referential constraints are present
[세션 통계 — ② 한 번]
1회차 (트리거 켬) 2회차 (트리거 끔) (비교) ① 주문 보관
redo size 42.7 MB 27.9 MB 0.1 MB
undo change vector size 12.4 MB 8.2 MB 0.02 MB
session logical reads 623,410 512,880 1,980
경과 5.9 초 3.6 초 0.08 초
ARC_DT가 NULL인 행 0 100,140 —