Skip to content

07화 · 실습과 기록 ​

여기서 하는 일: 히트율이 떨어진 이유를 재고, 메모리에서 한 블록 읽는 값을 재고, 스칼라 캐시가 깨지는 경계를 잰다.1_사건.md를 읽은 것은 "선배가 하는 걸 지켜본 것"이고, 이 문서를 끝내야 직접 해 본 것이 된다. 개념이 막히면 2_파고들기.md를 펼친다.

시간이 없는 주에는 STEP 0 → 1 → 2 → 7만 한다(약 40분).


STEP 0 — 직전 리비전을 연다 (3분) ★ 매주 처음 하는 일 ​

bash
docker start ora-hanorder
bash
cd 10_본편_튜너의_1년/07화_히트율_99퍼센트인데_서버가_탄다
cat ../06화_100만_번의_왕복/리비전/Q2_rev01.sql

지난주에 운영에 나간 바로 그 문장이다. 06화에서 잰 값은 Buffers 5,869였다(rev00은 1,026,849).

📌 07화에서는 리비전을 만들지 않는다. 오늘 재 보면 Buffers로는 더 줄일 것이 없다는 결론이 나온다(STEP 4 [E]). 그래서 이 화에는 리비전/ 폴더가 없고, Q2는 rev01 그대로 다음 화로 넘어간다.

전제를 확인한다.

sql
-- ① 06화를 마친 상태인가
SELECT index_name FROM user_indexes WHERE table_name IN ('T_ORD_BIG','M_CUS') ORDER BY 1;
-- 기대: IX_ORD_BIG_DT, IX_ORD_BIG_DT_AMT, PK_M_CUS   (06화의 IX_M_CUS_COVER 는 없어야 한다)

-- ② 데이터 지문
SELECT TO_CHAR(SUM(ORD_AMT),'999,999,999,999') FROM T_ORD_BIG;   -- 기대 255,398,623,700

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

지난주 Q2 의 힌트 29 글자를 지운 뒤, 운영 대시보드의 '버퍼캐시 히트율'이 99.9% 에서 경고선 아래로 떨어졌다.
히트율 = 1 − 물리적 읽기 ÷ 논리적 읽기.

Q1. rev01 은 rev00 보다 디스크(물리적 읽기)를 더 읽을까, 덜 읽을까, 같을까?
    ______________

Q2. 캐시가 빈 아침에 Q2 를 10 번 돌리는 '하루'의 히트율은?
    rev00 ______ %     rev01 ______ %

Q3. 캐시가 따뜻할 때 rev00 은 디스크를 0 블록 읽는다. 한 번 도는 데 걸리는 시간 중 CPU 는 몇 % 일까?
    ______________

Q4. T_ORD_BIG 에는 CUS_ID 2,000 종류가 500 번씩 돌아가며 들어 있다.
    (SELECT c.CUS_NM FROM M_CUS c WHERE c.CUS_ID = o.CUS_ID) 를 100 만 행에 붙이면
    M_CUS 쪽 Starts 는?
    ______________
▶ 적고 나서 펼치기

Q1 = 같다. 하루 동안 둘 다 11,626블록을 읽는다. 대부분 TEMP를 의심해서 "더 읽는다"라고 쓴다.

Q2 = rev00 99.89% · rev01 80.17%. 디스크 읽기는 같은데 히트율이 20포인트 가까이 떨어진다. 분모 때문이다.

Q3 = 거의 100%. rev00 한 번은 약 0.37초이고, 그 전부가 CPU 시간이다. "메모리에서 읽으니까 빠르다"는 믿음이 깨지는 자리다.

Q4 = 752,995. 대부분 2,000이라고 쓴다. 2,000종류 중 495개만 캐시에 자리를 얻었다.


STEP 2 — 히트율의 분모를 잰다 (10분) ★ 오늘의 본체 ​

bash
cd 실습
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 00_히트율의_분모.sql
powershell
Set-Location 실습
Get-Content 00_히트율의_분모.sql -Encoding UTF8 | docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1

약 10초 걸린다. 스크립트는 맨 앞에서 임시 객체를 치우고 통계를 다시 수집한다. 원본 테이블에는 쓰지 않는다. 캐시가 빈 테이블이 필요할 때는 T_ORD_BIG의 복사본 T_ORD_C07을 새로 만들고, 끝에서 지운다.

⚠️ 왜 복사본인가 ​

캐시를 비우려고 원본에 무언가를 쓰면 안 된다. 05화에서 본 것처럼 고수위선은 한 번 올라가면 롤백해도 안 내려온다. 원본에 한 줄을 넣었다 빼기만 해도 전체 스캔 블록 수가 바뀌어 다음 화의 숫자가 전부 어긋난다. 방금 만든 복사본은 아직 아무도 안 읽었으므로 캐시에 없다. 서버를 재기동하지 않고 '월요일 아침'을 만드는 방법이다.

세 단계에서 확인할 것 ​

단계무엇기대☐
[A]캐시가 따뜻할 때 rev00 / rev01 한 번씩논리 1,026,849 / 5,868 · 물리 0 / 0 · 히트율 둘 다 100.00☐
[B]캐시가 빈 하루: 복사본에 10번씩1·2번째만 물리 5,813 · 3번째부터 0 · rev00과 rev01이 같은 모양☐
[C]한 장으로 정리물리 11,626 = 11,626 · 히트율 99.89 → 80.17☐

눈으로 짚을 것 ​

[A] — 물리적 읽기 열
    ☐ 둘 다 0 인가?               → rev01 은 디스크를 더 읽지 않는다 (TEMP 의심 기각)
    ☐ cpu_cs 가 37 대 12 근처인가? → 디스크 0 인데 rev00 이 약 3 배 CPU 를 쓴다

[B] — 첫 두 줄
    ☐ 1 번째는 pr_direct 5,813, 2 번째는 pr_cache 5,813 인가?
      → 처음엔 캐시를 거치지 않고(direct path) 읽고, 두 번째에 캐시로 올린다. 둘 다 디스크다
    ☐ rev00 과 rev01 의 physical_reads 열이 줄마다 같은가?

[C] — 하루 합계
    ☐ PHYSICAL_READS 가 11,626 으로 같은가?          ← 오늘의 핵심
    ☐ HIT_PCT 가 99.89 와 80.17 인가?
    ☐ 첫 번째 실행만 보면 99.43 대 1.00 (안팎) 인가? ← 같은 5,813 블록을 읽고 99 와 1

📌 여기서 운영팀의 질문에 답이 나온다 ​

"디스크를 더 읽는 거 아니냐": 아니다. 11,626 = 11,626이다. "그럼 히트율은 왜 떨어졌나": 분모(논리적 읽기)가 10,268,450에서 58,639로 줄었기 때문이다. "그동안의 99.9는 뭐였나": M_CUS를 실행마다 100만 번 두드리던 낭비가 만든 숫자였다.


STEP 3 — 메모리에서 한 블록 읽는 값 (10분) ​

bash
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 01_논리읽기의_값.sql
powershell
Get-Content 01_논리읽기의_값.sql -Encoding UTF8 | docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1
단계무엇기대☐
[A]논리적 읽기 한 번에 CBC 래치를 몇 번 잡나rev00 1.009 (examination 1,018,012) · rev01 1.999 (pin 5,858)☐
[B]래치 4,096개 중 몇 개가 일했나rev00: 33개가 98.8% · rev01: 1,000번 넘는 래치 0개☐
[C]캐시 안의 Q2 객체 (V$BH)T_ORD_BIG 5,8xx · M_CUS 30 안팎 (서버 상태에 따라 조금 다르다)☐
[D]버퍼의 상태(복사본 M_CUS_C07)CTAS 직후 dirty 4 → 스캔 뒤 xcur 27 → UPDATE 뒤 dirty 31 + cr 27 → COMMIT 뒤 그대로☐
[A] — 두 줄을 나란히
    consistent gets examination   1,018,012   10        ← rev00 은 '들여다보고 끝'
    consistent gets pin               8,838   5,858     ← rev01 은 '핀 꽂고 여러 행'
    CBC latch gets                1,035,706   11,728
    ☐ 래치/LR 이 1.0 과 2.0 근처인가?
    ☐ 그런데 래치 총횟수는 88 배인가?     → 한 번에 덜 잡아도 횟수가 많으면 진다

[B] — rev00 의 LATCHES_OVER_1000
    ☐ 33 인가?   ☐ PCT_ON_THOSE 가 98.8 근처인가?
    => 그 33 개가 무슨 블록을 지키는지는 STEP 6 (SYSDBA) 에서 본다

[D] — 4 COMMIT 뒤
    ☐ dirty Y 31 이 그대로인가?   → 커밋은 데이터 블록을 디스크에 쓰지 않는다 (→ 13화)

V$LATCH_CHILDREN은 인스턴스 전체 카운터라 백그라운드 프로세스의 몫이 수백 정도 섞인다. 판정은 몇 배 차이인지로 한다.


STEP 4 — 스칼라 서브쿼리 캐시의 칸 (10분) ★ 06화가 남긴 질문 ​

bash
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 02_스칼라_캐시의_칸.sql
powershell
Get-Content 02_스칼라_캐시의_칸.sql -Encoding UTF8 | docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1

읽기만 한다. 아무것도 만들지 않는다.

채점표: 돌리기 전에 Starts를 먼저 적어 보자.

입력내 예상 Starts실측 Starts실측 Buffers
[A]c.RGN_ID (8종류)812 (전체 5,869)
[B]o.CUS_ID (2,000종류)752,995779,832
[B] 조인같은 답을 조인으로——5,856
[C]ORD_SEQ로 계산한 RGN_ID (입력 100만 · 결과 8종류)1,000,0001,005K

[D] 스윕 — 몇 개가 자리를 얻었나 ​

입력 NDVStarts자리를 얻은 값못 얻은 값
8880
6493,808586
128132,92211117
256215,03820155
512357,735329183
1,000568,432432568
2,000752,9954951,505
☐ 64 종류에서 이미 6 개가 자리를 못 얻는 것을 확인했는가?
☐ 752,995 = 495 + 1,505 × 500 을 손으로 맞춰 봤는가?
=> 스칼라 서브쿼리 캐시는 칸이 정해진 해시 테이블이고, 부딪히면 '안 적는다'.
   06화의 Starts 8 은 8 개가 안 부딪힌 운이었다.

[E] Starts 8이면 공짜인가 ​

Buffers / 회CPU 10회 (1/100초)
rev01 (스칼라)5,868119~121
스칼라 → 외부조인5,86260~63
☐ 양방향 MINUS 가 둘 다 0 인가?     ← 답이 같아야 비교할 자격이 있다
☐ Buffers 는 6 차이인데 CPU 는 절반인가?
=> M_RGN 은 8 번 열렸지만 메모판은 100 만 번 들여다봤다.
   T0(Buffers) 로는 개선이 아니다. 그래서 rev02 를 만들지 않는다.
   "왜 오라클이 알아서 조인으로 안 바꿨나" 는 08화의 질문이다.

STEP 5 — 네 명이 동시에 (선택 · 10분) ​

터미널 하나에서 일꾼 여러 개를 동시에 띄운다. 순서는 반드시 03a → 03b(여러 개 동시) → 03c를 지킨다.

bash
# Git Bash — rev00 네 명
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 03a_동시_준비.sql
for i in 1 2 3 4; do docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 03b_일꾼_rev00.sql & done; wait
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 03c_동시_결과.sql
powershell
# PowerShell — rev00 네 명
Get-Content 03a_동시_준비.sql -Encoding UTF8 | docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1
$f = Resolve-Path 03b_일꾼_rev00.sql
1..4 | ForEach-Object { Start-Job -ArgumentList $f -ScriptBlock { param($p) Get-Content $p -Encoding UTF8 | docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 } } | Wait-Job | Remove-Job
Get-Content 03c_동시_결과.sql -Encoding UTF8 | docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1

1 2 3 4를 1이나 1 2로 바꾸고, rev00을 rev01로 바꿔 가며 비교한다. 일꾼 하나가 Q2를 5번 돌린다.

동시에한 명 경과 (5회)CBC missessleepsresmgr 대기 (1인 평균)☐
rev00 × 11.86~1.94초000☐
rev00 × 21.88~1.91초수천~2만00~0.02초☐
rev00 × 42.29~3.59초2만~2만 8천00.53~1.42초☐
rev01 × 40.72~0.98초수십~수백00.17초☐
☐ misses 가 생겼는데 sleeps 는 0 인가?          → 놓친 래치를 전부 spin 으로 잡았다. 대기 이벤트엔 안 찍힌다
☐ 네 명일 때 NOT_ON_CPU_CS 와 RESMGR_CS 가 같은가? → 래치가 아니라 CPU 차례를 기다렸다 (Free 는 CPU 2 개)
☐ CBC_WAITS 가 0 인가?

ℹ️ Free에서는 여기까지만 보인다. CPU가 둘뿐이라 spin이 거의 다 성공하고 latch: cache buffers chains 대기는 생기지 않는다. 수백 세션이 같은 블록을 두드려 래치 대기가 쌓이는 대규모 EE 환경은 별권에서 다룬다.misses는 실행마다 크게 흔들린다(일꾼이 뜨는 시각이 조금씩 어긋나기 때문이다). 판정 기준은 "0이 아니다"와 "sleeps는 0" 두 가지다.


STEP 6 — 버퍼 헤더를 직접 본다 (선택 · SYSDBA · 5분) ​

SYSDBA가 필요하다. 시간이 없으면 건너뛰어도 된다. 이 화의 나머지는 SYS 없이 끝난다. ⚠️ 이 스크립트는 [B]에서 이 PDB의 버퍼 캐시를 비운다. 연습 컨테이너에서만 돌려야 한다.

bash
MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba < 90_XBH_SYSDBA.sql
powershell
Get-Content 90_XBH_SYSDBA.sql -Encoding UTF8 | docker exec -i ora-hanorder sqlplus -s "/ as sysdba"
단계무엇기대☐
[A]해시 구조의 숫자버킷 524,288 · CBC 래치 4,096 · _db_aging_touch_time 3☐
[B]touch countrev00 한 번 뒤 M_CUS 1 · 4초 간격 스캔 3번 뒤 T_ORD_BIG 4 · 쉬지 않고 3번 더 → 그대로 4☐
[C]바쁜 래치 → 블록래치 33개 = M_CUS 27블록 + PK_M_CUS 6블록☐
[D]체크포인트dirty 31 → 0☐
[E]스칼라 캐시를 8배로Starts 752,995 → 197,608 (0이 되지는 않는다)☐

[B]의 교훈: 블록마다 수만 번 만진 M_CUS는 1이고, 일곱 번 만진 T_ORD_BIG은 4다. touch count는 3초 간격으로만 오른다. SQL 하나가 1초 동안 몰아친 접근으로 캐시 자리를 독차지하지 못하게 막는 장치다.


STEP 7 — T1 리포트 5호 ★ 오늘의 산출물 ​

양식은 T1_단건SQL_튜닝리포트.md를 따른다. 오늘 쓰는 리포트는 SQL을 고친 리포트가 아니다. 운영 경보를 다룬 진단 리포트이고, 결론은 "고칠 것이 없다"와 "감시 지표를 바꾸자" 두 가지다.

┌──────────────────────────────────────────────────────────────────┐
│ T1 단건 SQL 튜닝 리포트 — 5호                                     │
│ 제목: 히트율은 건강 지표가 아니다                                 │
├──────────────────────────────────────────────────────────────────┤
│ 1. 대상      : Q2 (고객등급별 매출 집계) · rev01 유지 (변경 없음)   │
│                계기: 운영 대시보드 '버퍼캐시 히트율' 경고         │
│ 2. 측정 환경 : ora-hanorder · 26ai Free 23.26.2.0.0 · cpu_count 2    │
│                버퍼 캐시 864MB · T_ORD_BIG 1,000,000 / M_CUS 2,000 │
│ 3. 부하 조건 : ★ 비면 리포트 무효                                  │
│                ______________________________________________     │
│ 4. 현상      : ______________________________________________     │
│ 5. 원인      : ______________________________________________     │
│                [성능고도화 I권 p.441] [tgdba Tuning the Database   │
│                 Buffer Cache]                                     │
│ 6. 개선안    : 채택 ______________________________________        │
│                기각 ______________________________________        │
│ 7. 효과      : 물리 ______ → ______   논리 ______ → ______         │
│ 8. 정합성    : ______________________________________________     │
│ 9. 환경 의존성 ★ 히트율 자체가 환경 의존이다                       │
│                ______________________________________________     │
│ 10. 리스크   : ______________________________________________     │
│ 11. 롤백 절차: ______________________________________________     │
│ 12. 재측정   : ______________________________________________     │
└──────────────────────────────────────────────────────────────────┘

칸마다 들어가야 할 것 ​

3 「부하 조건」: 두 가지를 다 적는다. "단일 세션. 캐시가 빈 '하루' = 방금 만든 복사본 T_ORD_C07에 Q2를 10회. (선택) 동시 4세션 × 5회." 히트율은 부하 조건이 바뀌면 같은 SQL에서도 1%에서 100%까지 움직인다. 이 칸이 비어 있으면 숫자는 아무 뜻이 없다.

4 「현상」 · 5 「원인」

  • 현상: 히트율 99.9% → 경고선 아래. 같은 시점에 CPU 그래프는 내려갔다.
  • 원인(한 문장): "디스크 읽기는 그대로(11,626 = 11,626)이고, 논리적 읽기가 10,268,450 → 58,639로 줄어 비율이 99.89% → 80.17%가 되었다."

6 「개선안」: 채택안이 '없음'인 리포트다. 그것도 결론이다.

  • 채택: SQL 변경 없음. 감시 지표 추가 제안 (물리적 읽기 절대량 · SQL별 실행당 논리적 읽기 상위 10)
  • 기각: M_RGN 스칼라를 외부조인으로 바꾸는 안(Buffers 5,869 → 5,862, 7블록). T0 기준으로는 개선이 아니다. 다만 CPU는 절반(119~121 → 60~63, 10회)이므로 9번과 12번 칸에 기록하고 08화로 넘긴다

7 「효과」: 고친 게 없어도 잰 것은 적는다. 물리 11,626 → 11,626 · 논리 10,268,450 → 58,639 · CPU 약 3.7~4.0 초 → 약 1.2 초 (하루 기준, rev00 → rev01. 초 단위 값은 실행마다 흔들린다)

9 「환경 의존성」 ★

  • 히트율은 캐시 상태에 따라 같은 SQL에서도 1.00%(첫 실행)~100.00%(따뜻할 때)를 오간다
  • 처음 읽는 큰 테이블은 캐시를 거치지 않을 수 있다(direct path read). 그래도 물리적 읽기로 센다
  • Free는 CPU가 2개다. 동시에 실행하면 CPU 차례 기다림(resmgr:cpu quantum)으로 나타난다

10 「리스크」

  • 히트율 경보를 그냥 끄면 정말로 디스크 읽기가 늘어날 때도 알아채지 못한다. 끄지 말고 절대량 지표를 옆에 둔다
  • rev01이 쓰는 CPU의 절반은 스칼라 캐시 탐색이다. 스칼라로 고객명처럼 종류가 많은 값을 조회하면 Starts가 수십만으로 뛴다(실측 752,995)

11 「롤백 절차」: "SQL 변경 없음 → 해당 없음. rev01 자체의 롤백은 T1 4호(06화) 참조." 칸을 비우지 말고 '해당 없음'과 그 이유를 쓴다.

12 「재측정」: "대시보드에 물리적 읽기 합계와 SQL별 실행당 논리적 읽기를 추가한 뒤 1주 관찰. 08화에서 Q2의 스칼라 서브쿼리를 다시 잰다."


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

운영팀에 보낼 회신을 쓴다. 질문은 "튜닝하면서 뭘 건드린 거 아니냐"와 "이제 디스크를 더 읽는 거 아니냐" 두 가지였다.

4단계 프레임(현상/진단 → 원인 → 개선안 → 근거/효과)은 01화 3_실습과_기록.md와 같다.

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

① "정상 현상입니다. 문제없습니다"는 답이 아니다. 운영팀이 듣고 싶은 말일 뿐 증거가 아니다. 운영팀은 내일도 노란불을 본다. 디스크 읽기가 같다는 숫자(11,626 = 11,626)를 먼저 내놓는다.

② "히트율이 떨어진 건 좋은 일입니다"도 틀린 보고다. 떨어진 것 자체는 좋지도 나쁘지도 않다. 사실은 낭비가 사라져 분모가 줄었다는 것이다. 히트율이 떨어지는 나쁜 경우(정말로 디스크를 더 읽는 경우)도 있다는 점을 지워서는 안 된다.

③ 운영팀이 알아듣는 말로 쓴다. "논리적 읽기 10,268,450 → 58,639"로는 뜻이 전달되지 않는다. "디스크에서 가져오는 양은 그대로이고, 메모리 안에서 같은 고객 정보를 반복해 읽던 일이 175분의 1로 줄었습니다"라고 옮겨야 한다.

④ 대안을 같이 준다. 히트율을 보지 말라고만 하면 운영팀은 볼 게 없어진다. 무엇을 옆에 놓을지(물리적 읽기 절대량, SQL별 실행당 논리적 읽기)를 적는다.

⑤ CPU 그래프를 연결한다. 운영팀은 이미 "CPU가 내려갔다"는 것을 봤다. "히트율이 99.9%이던 기간에 CPU를 쓰던 바로 그 일이 사라진 것"이라고 두 관찰을 하나로 묶어 준다.


STEP 9 — 파인만 자가설명 ​

절차는 01화와 같다. 1단 백지 설명 → 2단 막힘 태그(최소 1개) → 3단 원천 복귀 → 4단 재설명 순서로 진행한다.

오늘 자주 나오는 태그 세 가지

태그전형적인 문장
#인과"디스크를 안 읽는데 왜 CPU를 쓰는지 설명하다가 막혔다" → 2_파고들기.md §2의 '블록 하나를 찾는 순서'
#용어"CBC 래치와 버퍼 핀(버퍼 Lock)이 각각 무엇을 지키는지 헷갈린다" → §3
#수치"752,995가 어떻게 495개로 바뀌는지 계산이 안 된다" → §9의 식에 직접 대입해 본다

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

  1. 조건 반전: "운영 서버를 재기동하지 않고 한 달 내내 띄워 두었다면, rev01 적용 뒤 히트율은 어떻게 보였을까?"
  2. 반례 요구: "히트율이 떨어졌는데 정말로 나쁜 일이 생긴 경우를 하나 든다면? 그때 분자와 분모는 각각 어떻게 움직이나?"
  3. 측정 지목: "'이 SQL이 서버를 태운다'를 히트율 없이 증명하려면 무엇을 재야 하나?"

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


완료 체크리스트 ​

  • [ ] STEP 0: Q2_rev01.sql을 열어 봤고, 06화의 커버링 인덱스가 남아 있지 않은 것을 확인했다
  • [ ] STEP 1: 보기 전에 예측 4개를 적었다
  • [ ] STEP 2: 물리적 읽기 11,626 = 11,626과 히트율 99.89 → 80.17을 직접 봤다
  • [ ] STEP 2: 첫 실행만의 99.43 대 1.00을 확인했다
  • [ ] STEP 3: 래치/LR 1.0 대 2.0과 래치 33개에 98.8%가 몰린 것을 확인했다
  • [ ] STEP 4: 입력 2,000종류의 752,995를 보고 495를 손으로 구했다
  • [ ] STEP 4: Starts 8인 스칼라가 CPU의 절반을 쓴다는 것을 봤다
  • [ ] STEP 7: T1 5호를 썼고, 3 「부하 조건」, 9 「환경 의존성」, 11 「롤백」 칸을 비우지 않았다
  • [ ] STEP 8: 운영팀 회신을 문장으로 풀어 썼다
  • [ ] STEP 9: 막힘 태그를 최소 1개 _막힘로그.md에 옮겼다

완결성 게이트: STEP 7의 3번 칸과 STEP 9의 태그가 비어 있으면 이 화는 미완성이다. 이 화의 진짜 산출물은 숫자가 아니라 "비율이 움직이면 분자와 분모를 따로 본다"는 습관이다.


다음 화로 넘기는 상태 ​

무엇값
T_ORD_BIG 인덱스2개(IX_ORD_BIG_DT, IX_ORD_BIG_DT_AMT). 07화에서는 아무것도 추가하지 않았다
M_CUS 인덱스PK_M_CUS 하나
Q1 현재 리비전rev02 · Buffers 91
Q2 현재 리비전rev01 유지 · Buffers 5,869. 07화에서는 리비전을 만들지 않았다
임시 객체없음 (T_ORD_C07 · M_CUS_C07 · T_CH07_*는 스크립트가 지운다)
남긴 빚인덱스 2개의 적재 비용 → 14화
열어 둔 질문Q2 rev01의 CPU 절반 = 스칼라 캐시 탐색 · 오라클은 왜 스칼라를 조인으로 안 바꿨나 → 08화

다음 → 08화: 오늘 남긴 스칼라 서브쿼리를 연다. 오라클이 SQL을 고쳐 쓰는 단계(쿼리 변환)에서 무슨 일이 일어나는지 보고, 06화가 넘긴 질문도 다룬다. 100만 행을 읽어 3행을 만드는 것이 맞는 요구인가?