Skip to content

14화 · 야간 배치가 아침을 넘긴다 ​

🗓️ 6월 3일 (월) · 13화에서 일주일 뒤 · 무대 ora-hanorder(한빛유통) + ora-burger(버거원 POS) 오늘 배울 것: 배치 시간을 잡아먹는 것은 행을 넣는 일 자체가 아니라, 행마다 따라붙는 일들이다. 그리고 무기마다 대가가 있다. 조각은 P1(정산 적재 배치)이고, 오늘이 첫 전진이다(rev00 → rev01 → rev02).


파일 세 개 ​

파일무엇을 하나시간
읽는다1_사건.md일요일 밤 체인이 아침 9시를 넘긴 날, 단계별로 나눠 재고, 02화부터 쌓인 적재 청구서를 정산하고, 하역장에서 무기를 고른 뒤, 무기 둘을 함께 들었다가 데는 하루40분
한다3_실습과_기록.md청구서 · 재적재 무기 · APPEND의 대가 · P1 한 문장 · 월말 정리 · Pruning · 버거원 3GB · 병렬 판독 · T3 1호90~150분
찾는다2_파고들기.mdDML 부수비용 다섯 · 무기 넷 · APPEND의 대가 · NOLOGGING · 파티션 유형 · Pstart/Pstop 판독 · LOCAL/GLOBAL · 첫 익스텐트 8MB · 병렬 내부필요할 때

1을 읽고 3을 따라 한다. 2는 막힐 때 펼친다. 시간이 없는 주에는 1_사건을 중단 지점 1까지 읽고 3_실습은 STEP 0, 1, 3(03만), 5, 10만 한다(약 50분, 버거원 없이).


지난 화에서 들고 오는 것 ​

13화 P1_rev00 메모"1,000건 커밋은 지금은 안전하다. 전진은 측정이 정당화할 때(14화)."
13화 「커밋 주기 기준」 #1"집합 연산 한 문장 → 커밋 한 번. 언두가 걱정이면 14화"
02 · 04 · 09화의 청구서인덱스 2개 → 3개의 적재 비용 · 04화 05_DML_청구서.sql(5만 건 1차 증거) · IX_ORD_BIG_DT 폐기 승인 대기
05화의 청구서월말 DELETE로는 분필 선이 안 내려간다(3,602 → 3,602 → 183) · 강도현 2021-03-30 "파티션은 유상 옵션이라 승인 못 받음"
10화가 넘긴 것인덱스 3개를 단 채 일반 INSERT로 100만 건 = 9분 13초. 오과장의 04시 마감과 통계 수집 단계가 부딪힌 진짜 이유
12화가 넘긴 것인덱스 맨 오른쪽 블록, 그 블록에 몰리는 쓰기를 흩는 방법과 대가

그리고 월요일 아침, 메시지가 세 개 와 있다.

"정산 화면에 지난주 정산이 반밖에 안 보여요. 새로고침할 때마다 늘어나요." (조민우, 09:03) "어젯밤 배치가 방금 끝났어요. 09시 12분. 04시 마감인데." (오과장, 09:14) "오늘 중으로 원인과 대책 부탁합니다. 숫자로요." (박팀장, 09:21)


오늘의 전개 — 두 번 틀리고, 무기 둘에 덴다 ​

내가 믿은 것측정 (연습 DB 복사본)
09:40"이번 주에 붙은 월말 정리가 범인이다"월말 DELETE는 0.06초. 재적재가 329초 = 체인의 99%(그중 309.5초가 리두 로그 교체 대기). PARALLEL(8)은 U - Unused
10:30(청구서 정산)5만 건 · 인덱스 0 → 3개: redo 2.44 → 38.55MB · 블록 변경 1,921 → 301,704
10:50"인덱스를 다 지우면 된다"낮의 Q1(91)과 Q4가 죽는다. 대신 끄고 켜기로 100만 건 329초 → 5.0초 · redo 916.6 → 0.6MB
11:10(비유) 하역장: 상자를 하나씩 vs 지게차와 팔레트
13:10무기의 대가TM LMODE 6 · 꺼진 동안 Q1 5,822 · DELETE로 비운 칸 무시 · 온라인 통계는 히스토그램을 안 모은다 · ORA-12838은 이 버전에서 안 남
14:00P1을 한 문장으로rev00 → rev02: undo 6.50 → 0.02MB · 정합성 통과 · 반쯤 보이던 정산의 정체
14:4005화의 청구서DELETE 3,602 그대로 · SHRINK redo 17.96MB · DROP PARTITION redo 0.01MB
15:30칸막이를 몇 개 여나rev00 ALL 1/37 5,868 · rev01 SINGLE 30/30 161
16:10"파티션 + 지게차 재적재면 끝"6월 한 칸 161 → 1,169(빈 블록 1,006 · 첫 익스텐트 8MB) → INITIAL 64K로 169
16:50버거원: 이미 파티션을 쓰는 곳ORD_LIST_HASH 3GB · 한 달 9,039(CTAS 982) · SUBSTR 가공 47,460

왜 이렇게 짰을까? 13화가 "왜 터지고 왜 느린가"였다면 14화는 "그럼 어떻게 빠르고 안전하게 하나"다. 그런데 무기를 고르는 일보다 무기의 대가를 재는 일이 더 길다. 무기 둘을 함께 들었다가 둘이 서로를 망치는 장면이 이 화의 클라이맥스다.


오늘 배우는 한 문장 ​

배치 시간을 잡아먹는 것은 행을 넣는 일 자체가 아니라, 행마다 따라붙는 일들이다. 인덱스 유지, 리두, 언두, 커밋을 행마다 치르지 않고 한 번에 치르는 것이 배치 튜닝이다. 그리고 그 무기마다 대가가 있다.

같은 100만 행 · 인덱스 3개경과redo
일반 INSERT · 켠 채 (운영 그대로)329초916.6MB
APPEND · 켠 채8.3초268.8MB
APPEND · 인덱스 끄고 → 켜기5.0초0.6MB

🔑 오늘의 비유 — 1층 하역장 (지게차와 팔레트) ​

하역장오라클
상자를 하나씩 들고 들어가 선반 빈칸에 꽂고, 대장 세 권에 한 줄씩 적는다일반 INSERT: 빈 블록을 재사용하고, 인덱스 3개를 행마다 고친다
지게차로 팔레트째 창고 맨 안쪽 빈 구역에 내려놓는다APPEND: 고수위선 위에 블록째 쓴다(직접 경로)
대장은 다 내린 뒤 품목 순으로 정렬해 새로 쓴다인덱스 끄고 켜기: UNUSABLE → 적재 → REBUILD
지게차가 도는 동안 창고 문에 노란 줄을 친다TM LMODE 6: 커밋할 때까지 다른 트랜잭션은 DML을 못 한다
대장을 새로 쓰는 동안에는 대장이 없다꺼진 인덱스: 조회가 조용히 전체 스캔으로 바뀐다(91 → 5,822)
중간 선반의 빈칸은 안 쓴다DELETE로 비운 블록을 APPEND는 재사용하지 않는다
구역의 남은 칸을 '비었음'으로 두고 다음 구역부터 쓴다파티션 첫 익스텐트(8MB)를 비워 둔다. 한 칸이 161 → 1,169
면허자가 한 명뿐인 하역장에서 "지게차 8대 불러"Free의 PARALLEL(8): 안 된다고 알려 주는 곳이 없다(U - Unused)

앞에서 나온 비유도 다시 나온다. 05화 3층 문서보관실의 분필 선(고수위선, 월별 칸막이), 02화 방문객 출입대장(가공한 키로는 칸막이도 못 고른다), 13화 정정 전 사본함(직접 경로는 슬립을 거의 넣지 않는다)이다.


☠️ 오늘의 함정 — 무기 둘을 함께 들면 ​

월별 파티션으로 나눴다          → 6월 한 칸만 연다 (SINGLE 30/30) · 161
주간 재적재를 APPEND 로 바꿨다  → 329초가 5초
둘을 같이                      → 6월 한 칸이 1,169 · 테이블 288 MB → 576 MB

에러가 없다. 실행계획도 PARTITION RANGE SINGLE로 멀쩡하다. Pstart/Pstop만 보고 "파티션 잘 탄다"고 보고하면, 다음 주부터 한 달 조회 비용이 7배가 된다. 처방은 파티션 저장 절에 INITIAL을 명시하는 것이다(169로 돌아온다). 자세한 내용은 2_파고들기.md §8.5에 있다.


실습 준비 ​

bash
docker start ora-hanorder
docker start ora-burger          # STEP 8 (버거원) 을 할 때만

13화를 마친 상태에서 시작한다. 실습/00_준비와_점검.sql이 이 상태를 확인한다(T_ORD_BIG 100만 · 인덱스 3 · ORD_ST 히스토그램 · T_ORD_STLM 10만 · PKG_ORD_STLM VALID · 언두 UNDOTBS1). 버거원은 L2 카드 §4 「14화 전에 — 파티션 복사본」을 마친 상태에서 시작한다. 이 DB는 12GB 한도에 바짝 붙어 있으므로 14화를 시작하기 전에 스테이징 테이블 두 개를 지운다.

bash
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 로 둘 다 안 지워진다

PowerShell에서는 먼저 $OutputEncoding = New-Object System.Text.UTF8Encoding $false를 한 줄 실행한다.

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

모든 스크립트는 몇 번을 돌려도 결과가 같다(두 번씩 돌려 확인했다). 원본 테이블에는 한 줄도 쓰지 않고, 전부 _C14, _P14 복사본에서 작업한다. ⚠️ 10은 버거원의 ORD_ITEM_LIST_HASH(약 3GB)를 지운다. 같은 설계를 다시 지어 비교할 자리를 마련하려는 것이다(이유는 스크립트 머리말과 STEP 8 참고). 버거원은 이 화가 마지막 무대다. ℹ️ 실습은 Docker로 띄운 Oracle Database Free에서 모두 끝난다. Free는 병렬 실행을 하지 않는다(힌트는 에러 없이 무시된다). 그래서 병렬은 '안 됐다는 증거'를 실측하고 실행계획을 판독하는 과제까지만 하고, 대규모 병렬은 별권에서 다룬다. 또 이 DB는 NOARCHIVELOG라서 직접 경로 적재의 redo가 운영(ARCHIVELOG)보다 작게 나온다. 표마다 그 점을 적어 두었다.


이 화의 산출물 ​

무엇어디
P1_rev01 · P1_rev02: 한 문장 INSERT … SELECT와 +APPEND(첫 전진)리비전/
T3 배치 SLA 리포트 ★ 새 양식 · 1호(일요일 밤 체인)40_보고서와_표준/템플릿/T3_배치_SLA_리포트.md · 3_실습 STEP 10
T2 개정: 「3-2 적재 비용」 칸 신설 · T2-002(IX_ORD_BIG_DT 폐기) 마무리40_보고서와_표준/템플릿/T2_인덱스힌트_변경승인서.md
덧붙임: 「통계 수집 정책서」 P3(온라인 통계는 히스토그램을 안 모은다) · 「커밋 주기 기준」 #1(언두 실측)통계수집_정책서.md · 커밋주기_기준.md

이 화가 다음으로 넘기는 것 ​

무엇어디로
커서 FOR 루프는 왜 느린가: rev00 0.89초와 rev01 0.08초의 차이가 어디서 나는지(SQL ↔ PL/SQL 왕복) · 한 문장으로 못 바꾸는 행 단위 로직 · T3 2호15화
운영 체인을 시간으로 보는 도구: 단계별 시각이 없어서 연습 DB에서 다시 재현해야 했던 것16 · 17화
「SQL 코딩 가이드」 후보: 파티션 키는 가공하지 않는다 · 적재 방식을 배치 머리에 적는다 · APPEND를 붙였으면 LOAD AS SELECT를 확인한다 · T3 · T2 v218화
대규모 병렬(QC · TQ 분배 · 다운그레이드 실측) · ARCHIVELOG에서의 NOLOGGING별권

← 13화 「안전 조치의 대가」 · 교재 전체 안내 · 다음 → 15화 「SQL은 다 고쳤는데 왜 느린가」