Skip to content

14화 · 실습과 기록 ​

여기서 하는 일: 일요일 밤 체인을 단계별로 재현하고, 청구서를 정산하고, 무기와 그 대가를 재고, P1을 한 문장으로 바꾸고, 파티션의 칸막이를 세어 보고, T3 배치 SLA 리포트 1호를 쓴다.1_사건.md를 읽은 것은 "선배가 하는 걸 지켜본 것"이고, 이 문서를 끝내야 직접 해 본 것이 된다. 개념이 막히면 2_파고들기.md를 펼친다.

시간이 없는 주에는 STEP 0 → 1 → 3(03만) → 5 → 10만 한다(약 50분). 오래 걸리는 01, 02와 버거원을 빼도 본체는 끝난다.


이 화의 실습 지도 ​

스크립트무엇컨테이너 · 계정소요
실습/00_준비와_점검.sql13화 종료 상태 확인 · 스냅샷 수첩 · 파티션 복사본 만들기 프로시저ora-hanorder · sqlp수 초
실습/01_청구서_정산.sql인덱스 0~4개 적재 비용 · T2-002 · FK·트리거 · 순번 키 역순〃15~20분
실습/02_재적재_운영그대로.sql인덱스 3개를 켠 채 일반 INSERT로 100만 건(선택)〃5~10분
실습/03_재적재_무기.sql★ APPEND · 끄고 켜기 · NOLOGGING · 꺼진 동안의 Q1 · 온라인 통계〃40초
실습/04_APPEND의_대가.sql배타 락 · ORA-12838 · 빈 칸 무시 · 파티션 + APPEND〃30초
실습/05_P1_집합처리.sql★ P1 rev00 · rev01 · rev02 · 정합성 · 남의 눈〃5초
실습/06_월말정리_DELETE와_파티션.sqlDELETE · SHRINK · DROP PARTITION · GLOBAL 인덱스〃10초
실습/07_Pruning_한빛.sqlPstart/Pstop · 키 가공 · LOCAL Prefixed/Nonprefixed〃10초
실습/08_병렬_강등.sqlPARALLEL(8)이 무시되는 증거 다섯〃수 초
실습/09_버거원_파티션.sql유형별 Pruning · 크기 · Nonprefixed PK · 이관 스크립트의 병렬도ora-burger · dev수 초
실습/10_버거원_공간회수와_재설계.sql★★ ORD_ITEM_LIST_HASH 삭제 · 같은 설계 다시 짓기〃1분
실습/99_정리.sqlC14 · P14 삭제 · 13화 종료 상태 확인ora-hanorder · sqlp수 초

PowerShell에서는 먼저 $OutputEncoding = New-Object System.Text.UTF8Encoding $false를 한 줄 실행한다. 실행 명령은 각 스크립트 머리에 적힌 두 줄(Git Bash / PowerShell)을 그대로 쓴다. 예를 들면 다음과 같다.

bash
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 실습/03_재적재_무기.sql

모든 스크립트는 몇 번을 돌려도 결과가 같다(두 번씩 돌려 확인했다). 원본 T_ORD_BIG, T_ORD, T_ORD_STLM, PKG_ORD_STLM에는 한 줄도 쓰지 않고, 전부 _C14, _P14 복사본에서 작업한다. 경과 시간(초)은 장비 사정을 타므로 redo, 블록 변경, Buffers로 대조한다.


STEP 0 — 직전 리비전을 연다 · 전제를 확인한다 (5분) ★ 매주 처음 하는 일 ​

bash
docker start ora-hanorder
cat 리비전/P1_rev00.sql      # 13화가 남긴 메모 : "전진은 측정이 정당화할 때(14화)"
bash
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 실습/00_준비와_점검.sql
확인기대
[전제] big_rows · big_idx · hist · stlm_rows · last_no · pkg · undo_ts1000000 · 3 · FREQUENCY · 100000 · 0 · VALID · UNDOTBS1
데이터 지문255,398,623,700
로그 모드NOARCHIVELOG · NO (← STEP 3에서 이 차이를 읽는다)
만든 것무효 0

버거원을 쓸 거면 (STEP 8) — 먼저 자리를 만든다 ​

버거원 DB는 파티션 복사본까지 넣으면 Free의 12GB 한도에 바짝 붙는다. 그래서 14화를 시작하기 전에 적재용 스테이징 테이블 두 개를 지운다(L2 카드 「공간이 빠듯할 때」 참고. 2~4.sql로 언제든 다시 만들 수 있다).

bash
docker start ora-burger
docker exec -i ora-burger sqlplus -s dev/dev@localhost/FREEPDB1 <<'SQL'
DROP TABLE ORD_TEMP PURGE;
DROP TABLE ORD_TEMP2 PURGE;
SQL
# PowerShell: @" ... "@ here-string 에 두 줄을 넣어 흘린다. 한 줄에 두 문장을 이어 쓰면 ORA-03405 로 둘 다 안 지워진다

이미 지워져 있으면 ORA-00942가 나온다. 정상이다.


STEP 1 — 예측을 봉인한다 (5분) ​

Q1. 인덱스 3개 켠 채 100만 건 재적재. 그중 '리두 로그를 갈아 끼우느라 기다린 시간' 은 몇 %?   ____
Q2. 5만 건 INSERT 의 redo — 인덱스 0개 2.44 MB. 3개면?   ____ MB
Q3. APPEND 로 넣으면 인덱스를 켠 채여도 redo 가 거의 0 이 된다.   예 / 아니오
Q4. APPEND 로 넣고 커밋 전에 같은 테이블을 SELECT 하면?   ______
Q5. 월별 파티션 + TRUNCATE + APPEND 재적재. 6월 한 칸 전체 스캔은 CTAS 직후(161)와 비교해?   같다 / 줄었다 / 늘었다
Q6. Free 에서 /*+ PARALLEL(8) */ 을 붙이면?   빨라진다 / 에러 / 아무 일도 없다
▶ 적고 나서 펼치기
대부분의 답실측
Q1"절반쯤"94~98%(329초 중 309.5초, 542초 중 532.2초 · log file switch (checkpoint incomplete))
Q2"7~8MB"38.55MB(인덱스 하나에 약 12MB)
Q3"예"아니오. 켠 채면 268.8MB다. 인덱스까지 꺼야 0.2MB가 된다
Q4"ORA-12838"(책)이 버전(23ai)에서는 읽힌다(1,001,000). 운영 버전이 다르면 책대로 막힌다
Q5"같다"늘었다. 1,169(칸마다 빈 블록 1,006 · 첫 익스텐트 8MB)
Q6"빨라진다"아무 일도 없다. Hint Report U - Unused · 계획 해시 동일

STEP 2 — 청구서 정산 (20분): 02·04·08·09화가 넘긴 것 ​

bash
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 실습/01_청구서_정산.sql

⏱ 15~20분 걸린다(실측 19분). 인덱스 구성을 바꿔 가며 5만 건을 서른 번 가까이 넣었다 뺀다. 시간의 대부분은 리두 로그 교체 대기다.

인덱스redo블록 변경논리 읽기☐
0개2.44MB약 1,920약 2,760☐
1개14.13MB약 102,480약 153,740☐
2개26.09MB약 201,060약 301,960☐
3개38.55MB약 301,700약 453,230☐
4개 (08화 기각안)50.62MB약 397,310약 596,980☐
T2-002: 3개에서 (ORD_DT)만 뺀 2개26.85MB약 201,130약 302,060☐

먼저 04화의 05_DML_청구서.sql이 낸 0개, 1개, 2개 값(2.44 · 14.13 · 26.10)과 같은지 본다. redo는 소수점까지 거의 같고, 블록 변경과 논리 읽기는 0.1% 안쪽으로 맞으며, 경과 시간(cs)은 크게 흔들린다.

눈으로 짚을 것 ​

☐ 인덱스 하나가 5만 건에 블록 변경 약 10만 = 행당 2번. 무엇을 두 번 고치나?   → 리프 블록 · 그 언두
☐ [제약·트리거] FK 를 붙이면 redo 는 그대로인데 논리 읽기만 늘었다 — 왜?       → 행마다 부모 PK 를 찾아간다
☐ 행 트리거를 붙이면 redo 가 12 MB 남짓 는다 — 인덱스 하나 값. 왜?              → 여러 행을 한 블록에 넣던 INSERT 가 한 행씩 넣는다
☐ [01-T1~T3] FK 나 트리거가 있으면 계획이 LOAD TABLE CONVENTIONAL · Note 에 이유
☐ [오른쪽 끝 블록] 보통 : 90-10 분할 107 · 역순 : 블록 변경 약 10만 · 범위 조건이 INDEX FULL SCAN 2,230

STEP 3 — 재적재: 운영 그대로 vs 무기 (10분) ★ ​

① 운영 그대로 (선택 · 5~10분) ​

bash
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 실습/02_재적재_운영그대로.sql
단계redo경과그중 로그 교체 대기☐
② 적재 + 커밋916.6MB5~10분(실측 329 · 542 · 585초)그 대부분(실측 309.5 · 532.2 · 556.3초)☐
④ 통계 수집1.4MB약 1초0☐
켠 채 채운 인덱스 크기약 4,370 · 3,555 · 5,370~5,510(갓 만든 것은 2,653 · 3,206 · 3,344. 일반 INSERT의 분할 위치는 회차마다 조금 다르다)☐

10화는 같은 배치를 9분 13초로 쟀다. 시간은 흔들려도 redo 916.6MB는 흔들리지 않는다. 6분을 기다리기 어렵다면 건너뛰고 위 표의 숫자로 읽으면 된다.

② 무기 (실습/03 · 30초) ​

bash
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 실습/03_재적재_무기.sql
단계redo경과☐
[B] APPEND · 켠 채268.8MB8~11초(2회)☐
[E] 일반 · 끄고 → 켜기48.4 + 0.4MB약 1 + 5초(2회 같음)☐
[C] APPEND · 끄고 → 켜기0.2 + 0.4MB약 0.25 + 4.7초☐
[D] [C] + NOLOGGING[C]와 같다☐

눈으로 짚을 것 ​

☐ [B] 직후 : NUM_ROWS 1000000 · NOTES STATS_ON_LOAD · 그런데 ORD_ST 의 HISTOGRAM 은? → NONE (원본 FREQUENCY)
      → "APPEND 로 바꾸면 통계 수집 단계를 빼도 된다" 는 틀렸다. 그 단계는 1초였다
☐ [C] 인덱스를 끄면 세그먼트가 0 이 된다 (UNUSABLE)
☐ [03-C1] 꺼진 동안 Q1 : TABLE ACCESS FULL 약 5,820  →  [03-C2] 켠 뒤 : 91        ← 끄고 켜기의 대가
☐ 다시 켠 인덱스 = 갓 만든 크기 (2,653 · 3,206 · 3,344)
☐ [C] ≈ [D] — 왜 NOLOGGING 이 아무것도 안 바꾸나?   → 이 DB 는 NOARCHIVELOG (2_파고들기 §5)

STEP 4 — APPEND의 대가 (10분) ​

bash
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 실습/04_APPEND의_대가.sql
블록기대☐
[1] 일반 INSERTTM LMODE 3 · 다른 트랜잭션: 넣을 수 있다☐
[1] APPEND계획 LOAD AS SELECT · TM LMODE 6 · 다른 트랜잭션: ORA-00054☐
[2] 커밋 전 SELECT1,001,000(책의 ORA-12838은 이 버전에서 안 난다)☐
[3] DELETE 33만 → 되채움일반 6,016블록 · 전체 스캔 5,889 / APPEND 7,990 · 7,862☐
[4] 파티션 CTAS 직후288MB · 6월 161☐
[4] TRUNCATE → APPEND 뒤576MB · 6월 1,169 · 6월 칸 full 160 · 빈 블록 1,006☐
[4] INITIAL 64K로 같은 일72MB · 6월 169 · 빈 블록 5☐
☐ [1] 이 적재가 아침까지 가면 낮 업무는 이 테이블에 무엇을 못 하나?
☐ [3] 월말 DELETE + 일상 APPEND 테이블은 매달 어떻게 되나?
☐ [4] '칸막이를 하나만 연다(SINGLE 30)' 는 맞는데 왜 7배인가? — Pstart/Pstop 만 보고 보고하면 놓치는 것

STEP 5 — P1을 한 문장으로 (10분) ★ 오늘의 조각 ​

bash
cat 리비전/P1_rev01.sql 리비전/P1_rev02.sql
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 실습/05_P1_집합처리.sql
판경과redoundo커밋☐
rev00 루프 · 1,000건 커밋약 0.9초28.66MB6.50MB101☐
rev01 INSERT … SELECT0.08~0.23초4.47MB0.26MB2☐
rev02 + APPEND약 0.11초0.08MB0.02MB2☐

커밋 수에는 TRUNCATE의 커밋 1이 들어 있다. redo는 회차마다 소수점 둘째 자리에서 조금 흔들린다.

정합성 — 체크리스트 B (다섯 개 전부) ​

new_rows · old_rowsnew_sum · old_sumnew−old · old−newdup_seq☐
100000 · 10000025,519,833,100 · 25,519,833,1000 · 00☐
☐ seq_order_diff = 0 — 정산번호가 같은 건 '맞아서' 가 아니라 T_ORD 가 ORD_SEQ 순으로 쌓여 있어서다 (체크리스트 E)
☐ [남의 눈] rev00 이 5만 번째 행을 넣는 순간 남에게 보이는 정산 = 50000 건  ← 09:03 조민우
☐ rev02 커밋 뒤 남의 눈 = 100000
☐ 13화 「커밋 주기 기준」 #1 과 충돌하나?  → 아니다. #1 에서 멈추는 경우이고, '언두가 걱정이면' 에 숫자(0.02 MB)가 붙었다

STEP 6 — 05화의 청구서: 월말 정리 (10분) ​

bash
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 실습/06_월말정리_DELETE와_파티션.sql
정리 방법redo그 뒤 전체 스캔☐
DELETE 한 달(17,235행)4.84MB3,602 → 3,602☐
SHRINK SPACE(매달 청소)17.96MB3,489☐
DROP PARTITION0.01MB3,630 → 3,505☐
[4] DROP 뒤 GLOBAL 인덱스UNUSABLE · 이력 조회 ORD_SEQ = 4242 → 전체 스캔 3,505☐
[4] UPDATE GLOBAL INDEXES로VALID · ORPHANED_ENTRIES YES · 같은 조회 3☐
☐ 05화의 3,602 가 같은 생성식에서 그대로 나왔나?
☐ 한 달 DELETE 는 0.06초다. 그런데 왜 '청구서' 인가?  → 시간이 아니라 읽는 양과 매달의 청소
☐ 파티션으로 지은 쪽은 세그먼트 30개 · 240 MB — 파티션 없는 쪽 29 MB 와 왜 다른가? (2_파고들기 §8.5)

STEP 7 — 칸막이를 몇 개 여는가: Pruning (10분) ​

bash
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 실습/07_Pruning_한빛.sql

채점표: 돌리기 전에 각 줄의 Pstart / Pstop을 먼저 적어 보자.

조건내 예상실측 Pstart/PstopBuffers
[A] TO_CHAR(ORD_DT,'YYYYMMDD') BETWEEN … (rev00)1 / 37 (ALL)5,868
[B] ORD_DT >= … AND < … (rev01)30 / 30 (SINGLE)161
[C] 바인드 변수KEY / KEY161
[D] TRUNC(ORD_DT,'MM') = …1 / 375,868
[E] 6 ~ 8월30 / 32 (ITERATOR)493
[F] 달력 테이블이 고른 달KEY / KEY163 · 165
[G] LOCAL Prefixed (ORD_DT, ORD_AMT)옵티마이저는 6월 칸 FULL161(강제하면 89)
(기준) 원본 T_ORD_BIG · Q1 rev02—91
[H] LOCAL Nonprefixed (CUS_ID) · 날짜 없이1 / 37 · 인덱스 Starts 36572
[H] 같은 인덱스 · 6월과 함께30 / 3016
[H] GLOBAL (CUS_ID)ROWID504
☐ 칸막이도 '가공하지 않은 키' 만 알아듣는다 — TRUNC(…,'MM') 처럼 월 단위 가공도 안 된다
☐ 파티션 한 칸 FULL(161) 이 커버링 인덱스(91)보다 많다 — 파티션은 무엇을 빠르게 해 주나?

STEP 8 — 버거원: 이미 파티션을 쓰는 곳 (15분) ​

bash
docker exec -i ora-burger sqlplus -s dev/dev@localhost/FREEPDB1 < 실습/09_버거원_파티션.sql
확인기대☐
[1] 크기ORD 1 · 176MB / ORD_LIST 24 · 384MB / ORD_LIST_HASH 192 · 3,072MB☐
[1] 2012년 6월 칸ORD_LIST full 971 · 빈 1,006 / ORD_LIST_HASH 서브마다 full 약 121 · 빈 1,006☐
[2a] ORD_YM = '201206'LIST SINGLE · 1,980☐
[2b] SUBSTR(ORD_DT,1,6) = '201206'LIST ALL 1~25 · 47,460☐
[2c] ORD_DT LIKE '201206%'LIST ALL + 로컬 인덱스 24번 · 41,897☐
[2e] ORD_LIST_HASH 한 달SINGLE + HASH ALL 1~8 · 9,039☐
[2f] (기준) 파티션 없는 ORD1,089☐
[3] PK (ORD_NO, ORD_YM)에 번호만RANGE ALL · 50 / 번호 + 월 3 / ORD 4☐
[4] 이관 스크립트가 남긴 병렬도DEGREE 1(만들 때 PARALLEL 8 → 바로 NOPARALLEL) · Parallel execution FALSE☐

★★ 3GB의 정체 — 지우고, 다시 지어 본다 ​

⚠️ 10은 ORD_ITEM_LIST_HASH(약 3GB)를 지운다. 되돌리려면 L2 카드 §4를 다시 돌린다(약 40분). 이유: 같은 설계를 다른 방법으로 다시 지어 비교하려면 약 1.9GB가 필요한데, 버거원 DB는 12GB 한도까지 1GB도 채 남아 있지 않다(실측: PDB 세그먼트 합계 11,321MB, 지운 뒤 8,082MB). ORD_ITEM_LIST_HASH는 [1]에서 크기를 이미 쟀고 ORD_LIST_HASH와 같은 병을 앓고 있다. 버거원은 14화 이후로는 쓰지 않는다.

bash
docker exec -i ora-burger sqlplus -s dev/dev@localhost/FREEPDB1 < 실습/10_버거원_공간회수와_재설계.sql
같은 100만 행 · LIST 25 × HASH 8할당고수위선 아래6월 전체 스캔☐
원래(빈 테이블 + APPEND)3,072MB223,4109,039☐
CTAS1,536MB26,792982☐
CTAS + INITIAL 64K379MB25,640998☐
DEV 세그먼트 합계지우기 전 10,794MB → 지운 뒤 7,551MB☐
☐ 3GB 의 절반은 '자리'(192칸 × 8 MB), 절반은 'APPEND 가 비워 둔 빈 블록' — 읽기를 9배로 만든 건 어느 쪽?
☐ 해시 8조각은 무엇을 위해 나눴나? 버거원 화면 중 ORD_NO + ORD_YM 으로 찾는 것이 있나? — 근거가 없으면 설계가 아니다

버거원 작업이 끝났으면 docker stop ora-burger로 멈춘다(메모리 1~1.5GB 회수).


STEP 9 — 병렬 판독 과제 (Free 에서는 못 잰다) ​

① '안 됐다'는 증거 다섯 — 이 DB에서 잰다 ​

bash
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 실습/08_병렬_강등.sql
증거기대☐
힌트 없음 vs PARALLEL(o 8)의 Plan hash value같다(4189269332) · PX 줄 없음☐
Hint ReportU - Unused PARALLEL(o 8)☐
V$PQ_TQSTAT · V$PX_SESSION0 · 0☐
queries parallelized · downgraded to serial0 · 0(강등 기록조차 없다)☐
FORCE PARALLEL QUERY · ENABLE PARALLEL DML 뒤 PQ_STATUSDISABLED 그대로 · 에러 없음☐

② 판독 — EE의 병렬 계획 (2_파고들기 §9.3의 계획을 보고 답한다) ​

① QC 는 몇 번 줄인가?
② Granule 은 블록 범위인가, 파티션인가? 어느 줄에서 아나?
③ TQ 는 몇 개이고, 각각 무엇을 어디로 보내나?
④ 두 테이블을 HASH 로 재분배했다. PQ_DISTRIBUTE(o BROADCAST NONE) 이면 9 · 13번 줄은?
⑤ DOP 4 를 다 못 얻으면 무슨 일이 일어나고, 어디에 기록되나?
▶ 적고 나서 펼치기

① 1번 PX COORDINATOR다(2번 PX SEND QC로 결과를 받는다). ② 블록 범위다. 10번과 14번이 PX BLOCK ITERATOR다. 파티션 단위라면 PX PARTITION RANGE ALL 같은 줄이 그 자리에 온다. ③ 4개다. :TQ10000(M_CUS → 조인 서버, HASH), :TQ10001(T_ORD_BIG → 조인 서버, HASH), :TQ10002(1차 집계 → 2차 집계 서버, HASH), :TQ10003(최종 집계 → QC, P->S). ④ 작은 쪽(M_CUS)을 모든 소비자에게 통째로 보낸다. PX SEND BROADCAST가 되고 PQ Distrib은 BROADCAST다. 큰 쪽(T_ORD_BIG)은 재분배 없이(NONE) 읽은 서버가 그대로 조인하므로 :TQ10001이 사라진다. ⑤ 서버를 덜 받은 만큼 DOP를 낮춰 돈다(또는 직렬로 돈다). V$SYSSTAT의 'Parallel operations downgraded …' 값이 올라간다. PARALLEL_MIN_PERCENT를 걸어 두면 DOP를 낮추는 대신 ORA-12827로 실패한다. Free에서는 ⑤의 통계조차 오르지 않는다(①표: downgraded 0). 계획을 세울 때부터 직렬이기 때문이다.

대규모 병렬 실측(서버 수, TQ별 행 분포, 다운그레이드)은 별권에서 EE로 한다.


STEP 10 — T3 배치 SLA 리포트 1호 + T2 개정 ★ 오늘의 산출물 ​

양식: T3_배치_SLA_리포트.md (이 화 제정) · T2_인덱스힌트_변경승인서.md (이 화 개정: 「적재 비용」 칸) · 정합성 회귀 체크리스트 · 커밋 주기 기준

┌────────────────────────────────────────────────────────────────────────────────┐
│ T3 배치 SLA 리포트 — 1호   주간 야간 체인 (일요일 밤)                            │
├────────────────────────────────────────────────────────────────────────────────┤
│ 1. 배치 · 창    : 트리거 일 22:00 · 마감 월 04:00 · 6/2 실제 끝 월 09:12 (초과 5h12m) │
│ 2. 환경         : 연습 DB 복사본 · 23ai Free · NOARCHIVELOG · 리두 10MB×2 · 단독 실행 │
│ 3. 단계 분해    : (아래 표)                                                     │
│ 4. 처리량       : 재적재 100만 행 — 지금 0.329 ms/행 · 바꾼 뒤 0.005 ms/행         │
│                   redo 약 961 B/행 → 약 0.6 B/행                                 │
│ 5. 자원         : redo 916.6 MB → 0.6 MB · undo 344.4 MB → 0.09 MB               │
│ 6. 재기동 · 멱등 : 재적재 = TRUNCATE 부터 (멱등) · P1 rev02 = TRUNCATE + 한 문장 (멱등) │
│                   rev00 은 중간 실패 시 '반쯤 적재' (13화 E·H)                   │
│ 7. 동시 실행 영향: 적재 동안 TM LMODE 6 (남의 INSERT 불가) · 인덱스 꺼진 동안       │
│                   Q1 91 → 5,822 (조용히) · P1 적재 동안 정산 0건                 │
│ 8. 추세         : 측정 불가 — 운영 로그에 단계별 시각 없음 (재발방지 1)            │
│ 9. 개선 이력    : P1 rev00 → rev02 · 재적재 방식 (일반 → APPEND + 끄고 켜기)      │
│10. 정합성       : 체크리스트 A·B·E·H (STEP 5)                                    │
│11. 커밋 주기    : 「커밋 주기 기준」 #1 (집합 연산 → 커밋 한 번) · 언두 0.02 MB     │
│12. 재발방지     : ① 단계별 시각 기록 ② 통계 수집 단계 유지(히스토그램)             │
│                   ③ PARALLEL(8) 제거 후 운영 재측정 ④ 파티션 예산(근거 STEP 6)    │
│                   ⑤ 파티션 도입 시 INITIAL 명시 (STEP 4 [4])                      │
└────────────────────────────────────────────────────────────────────────────────┘

3번 「단계 분해」 표는 연습 DB 실측으로 채우고, 칸마다 출처 스크립트를 적는다.

단계지금바꾼 뒤출처
① 재적재일반 INSERT · 인덱스 3개 켠 채 329초 · redo 916.6MBAPPEND + 끄고 켜기 5.0초 · redo 0.6MB02 [A] · 03 [C]
① 통계 수집1.06초1.06초(유지: 온라인 통계는 히스토그램을 안 모은다)02 [A] · 03 [B]
② 월말 이력 정리DELETE 0.06초 · 전체 스캔 3,602 그대로(파티션 승인 시) DROP PARTITION 0.04초 · redo 0.01MB06
③ 월마감 집계PARALLEL(8) · 0.05초 · Hint Unused힌트 제거 · 운영에서 재측정08
④ P1rev00 0.89초 · redo 28.66MBrev02 0.11초 · redo 0.08MB05
합계약 331초약 6.3초

⚠️ 연습 DB의 초를 운영의 초로 옮기지 않는다. 운영 로그에 단계별 시각이 없으므로 이 표로 알 수 있는 것은 '어느 단계가 몸통인가'와 '방식을 바꾸면 무엇이 몇 배 줄어드는가'까지다. 운영의 초는 재발방지 1번을 적용한 뒤에 잰다.

T2-002 마무리 — IX_ORD_BIG_DT 폐기 (04화 승인 대기) ​

개정된 T2의 3-2 「적재 비용」 칸을 채운다(STEP 2의 마지막 줄).

적재 방식 : 일반 INSERT (지금) / APPEND + 끄고 켜기 (바꾼 뒤)
5만 건     : 인덱스 3개 redo 38.55 MB → (ORD_DT) 만 뺀 2개 redo 26.85 MB (−11.70 MB · 30%)
100만 건   : 일반 INSERT 면 행마다 청구 / 끄고 켜기면 재생성 시간만 (STEP 3 [C] 재생성 3개 4.74초 중 1개 몫)
조회 영향  : Q1 rev02 는 (ORD_DT, ORD_AMT) 를 쓴다 → 91 유지 (STEP 7 기준)
선결 조건  : T_ORD_BIG 참조 SQL 전수 · DBA_INDEX_USAGE 관찰 — 04화 그대로

적재 방식을 먼저 적는 이유: 같은 인덱스라도 일반 INSERT로 켠 채 넣으면 '행마다' 비용이 청구되고(5만 건에 12MB), 끄고 켜기로 넣으면 '재생성 몇 초'로 바뀐다. 이 칸이 비어 있으면 인덱스 하나의 값을 정할 수 없다. T2를 고친 것도 그래서다.


STEP 11 — 서술 답안 (400~600자) ​

박팀장에게 보내는 회신. "배치가 왜 아침을 넘겼고, 다시는 안 넘기려면 무엇이 필요한가."

▶ 선배의 첨삭 포인트 (쓰고 나서)

① "월말 정리 때문"으로 끝내지 않는다. 이번 주에 달라진 것은 월말 정리였지만, 체인의 99%는 재적재였다(연습 DB에서 재적재 329초, 월말 정리 0.06초). 넘치게 한 것과 채운 것을 나눠서 쓴다.

② 인덱스를 "지우겠다"고 쓰지 않는다. 인덱스는 낮에 Q1의 91과 Q4 포스트잇을 번다. "적재하는 동안만 끄고 다시 짓는다"고 쓰고, 그 몇 초 동안 Q1이 5,822로 떨어진다는 대가도 함께 쓴다.

③ 연습 DB의 초를 약속하지 않는다. "329초 → 5초"는 연습 DB에서의 비율이다. 운영의 초는 단계별 시각을 남긴 뒤 다음 주에 보고한다.

④ 무기 둘을 함께 쓸 때의 함정을 미리 쓴다. 파티션 예산을 올리면서 "INITIAL을 명시하지 않으면 한 달 조회가 7배"라는 점도 같이 적는다. 예산이 나온 다음에 알면 늦다.


STEP 12 — 파인만 자가설명 ​

1단 백지 설명 → 2단 막힘 태그(최소 1개) → 3단 원천 복귀 → 4단 재설명.

태그전형적인 문장
#인과"인덱스를 켠 채 넣으면 왜 리두 로그 교체를 기다리게 되는지 설명하다 막혔다" → §2.3
#용어"Pstart/Pstop의 KEY와 숫자의 차이를 말로 못 하겠다" → §7.1
#수치"파티션 6월 칸이 왜 161이 아니라 1,169인지 블록으로 못 나눠 보겠다" → §8.5

4단 되묻기 3문 (오늘 버전) ​

  1. 조건 반전: "재적재 대상 테이블에 FK가 있으면 오늘의 무기는 어떻게 되나?"
  2. 반례 요구: "파티션으로 바꿨는데 조회가 더 비싸지는 경우 둘은?"(힌트: 161 vs 91 · 1,169)
  3. 측정 지목: "'PARALLEL 8이 효과가 있었다'를 증명하려면 무엇을 재야 하나? 이 DB에서 그게 되나?"

태그는 _막힘로그.md로 옮긴다.


정리 — 한빛유통을 13화 종료 상태로 ​

bash
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 실습/99_정리.sql

기대: c14_left 0 · 1000000 · 3 · FREQUENCY · 100000 · 0 · VALID · UNDOTBS1 · 원본 T_ORD_BIG 5,923블록 · 인덱스 2,653 · 3,206 · 3,344


완료 체크리스트 ​

  • [ ] STEP 0: P1_rev00의 13화 메모를 읽었고, 버거원 스테이징 두 개를 지웠다
  • [ ] STEP 1: 보기 전에 예측 6개를 적었다
  • [ ] STEP 2: 인덱스 0 → 3개에서 redo 2.44 → 38.55MB를 확인했다
  • [ ] STEP 3: 329초 → 5초를 확인했고, [B] 직후 ORD_ST 히스토그램이 사라진 것도 봤다
  • [ ] STEP 4: LMODE 6 · 빈 칸 무시 · 파티션 6월 161 → 1,169를 봤다
  • [ ] STEP 5: P1 rev02를 돌리고 정합성 다섯 항목을 통과시켰다
  • [ ] STEP 6: DELETE는 3,602 그대로이고 DROP PARTITION은 redo 0.01MB인 것, GLOBAL 인덱스가 UNUSABLE이 되는 것을 봤다
  • [ ] STEP 7: rev00 1/37, rev01 30/30을 먼저 예측해 적고 대조했다
  • [ ] STEP 8: 버거원 3GB의 정체를 쟀다(선택)
  • [ ] STEP 9: U - Unused를 확인하고 판독 과제 5문에 답했다
  • [ ] STEP 10: T3 1호를 쓰면서 「동시 실행 영향」과 「추세(측정 불가)」 칸을 채웠고, T2-002 「적재 비용」 칸도 채웠다
  • [ ] STEP 12: 막힘 태그 최소 1개를 _막힘로그.md에 옮겼다
  • [ ] 정리: 99로 13화 종료 상태를 확인했다

완결성 게이트: STEP 10의 「동시 실행 영향」, STEP 5의 정합성, STEP 3의 히스토그램 확인이 비어 있으면 이 화는 미완성이다.


다음 화로 넘기는 상태 ​

무엇값
ora-hanorder변화 없음. 13화 종료 상태 그대로(T_ORD_BIG 인덱스 3 · ORD_ST 히스토그램 · T_ORD_STLM 10만 · PKG_ORD_STLM 원본 · C14/P14 0)
ora-burgerORD_ITEM_LIST_HASH 삭제됨(STEP 8을 했다면) · ORD_TEMP/ORD_TEMP2 삭제됨. 14화가 마지막 무대
P1 현재 리비전rev02(APPEND · 커밋 한 번). 리비전 파일로만 남는다. 연습 DB의 PKG_ORD_STLM은 원본 그대로
새 양식 · 개정T3 배치 SLA 리포트(제정 · 1호) · T2 개정(「적재 비용」 칸 · T2-002)
열어 둔 것커서 루프의 내부 비용 → 15화 · 운영 체인의 시간 → 16·17화

다음 → 15화 「SQL은 다 고쳤는데 왜 느린가」: 오늘 P1은 한 문장이 됐다. 다음 주에는 한 문장으로 바꿀 수 없는 배치가 온다.