Skip to content

16화 · 실습과 기록 ​

여기서 하는 일: AWR SOP 9단계를 직접 밟는다. 부하를 만들어 걸고, 스냅샷 둘을 찍고, 리포트를 뽑아 9칸을 정해진 순서로 읽는다. 두 구간을 겹쳐 본 뒤 T5, T7, T8 1호를 쓴다.1_사건.md를 읽은 것은 "선배가 하는 걸 지켜본 것"이고, 이 문서를 끝내야 직접 해 본 것이 된다. 개념이 막히면 2_파고들기.md를 펼친다.

시간이 없는 주에는 STEP 0 → 1 → 3 → 4 → 6 → 10만 한다(약 70분, 그중 부하 24분은 기다리는 시간이다). STEP 9의 한 시간은 선택이다.


이 화의 실습 지도 ​

스크립트무엇계정소요
실습/00_준비와_점검.sql15화 종료 상태 · 부하 발생기 · 원본 지문 · 보정 배치 복사본(C16)sqlp10초
실습/01_AWR_현황_SYSDBA.sqlSOP 1 · 2 · 3: 어디서 · 팩 · 간격 · 보존 · 스냅샷 · 저장소 · 자원 여유SYS수 초
실습/02_구간_스냅샷_SYSDBA.sql★ SOP 4~7: 발사기와 창 둘 · S1 · (보정 배치) · S2 · 루트와 PDBSYS(+ sqlp)12분 × 2
실습/03_AWR_리포트_SYSDBA.sql★ SOP 8: 리포트 한 장(AWR_REPORT_TEXT) → 파일SYS수 초
실습/04_9칸_직접_읽기_SYSDBA.sql★ 9칸을 DBA_HIST_*에서 직접 · 구간 A · B · H 나란히 · ⑨ 대조SYS수 초
실습/05_AWR_비교_SYSDBA.sql★ 두 구간 비교(AWR_DIFF_REPORT_TEXT) → 파일SYS수 초
실습/06_AWR_SQL_리포트_SYSDBA.sqlSQL 하나의 리포트(AWR_SQL_REPORT_TEXT)SYS수 초
실습/07_PDB_레벨_AWR_SYSDBA.sqlPDB 레벨 AWR은 어디까지 되나SYS(+ sqlp)10초
실습/08_정기점검_SYSDBA.sqlT8 1호의 숫자: 일간 5칸 · 주간 4칸SYS수 초
실습/09_부하모델의_Q2.sql부하 발생기의 Q2 vs 운영 Q2 rev01 vs 08화 보류안(부하 없이)sqlp15초
실습/99_정리.sqlC16 삭제 · 15화 종료 상태 확인(AWR 스냅샷과 런 기록은 남긴다)sqlp수 초
★★ L1/05_부하_돌리기.sh · .ps115화의 발사기(환경 폴더 · 다시 설치하지 않는다)sqlp12분 × 2(+ 62분)

SYS로 돌리는 스크립트가 많다. Git Bash에서는 MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba < …(빼면 /가 경로로 바뀐다), PowerShell에서는 Get-Content … -Encoding UTF8 | docker exec -i ora-hanorder sqlplus -s / as sysdba로 돌린다. PowerShell에서는 먼저 $OutputEncoding = New-Object System.Text.UTF8Encoding $false 한 줄을 실행한다. 원본 테이블에는 한 줄도 쓰지 않는다. 부하 발생기는 *_LD 작업 테이블에만, 보정 배치는 C16 복사본에만 쓴다. 발사기가 런 앞뒤로 원본 지문을 찍는다. AWR 스냅샷은 지우지 않는다. 보존 8일이 지나면 저절로 지워진다. 17화에서 이 화의 구간을 다시 연다.


STEP 0 — 전제 확인 · 지난 리포트의 기한 (5분) ★ 매주 처음 하는 일 ​

bash
docker start ora-hanorder
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 실습/00_준비와_점검.sql
확인기대☐
[전제] big_rows · big_idx · hist · stlm_rows · last_no · pkg · driver · ld_tabs · driver_alive1000000 · 3 · FREQUENCY · 100000 · 0 · VALID · VALID · 3 · 0☐
원본 지문T_ORD_BIG 1000000 / 255,398,623,700 · T_ORD_STLM 100000 / 25,519,833,100 · T_STLM_NUM 0☐
설정cpu_count 2 · job_queue_processes 1 · control_management_pack_access DIAGNOSTIC+TUNING☐
지난 런15화 시운전 기록이 남아 있다(설치할 때 지우지 않았다)☐
[확인] 만든 것정산 100020 · 고객 1997 · 이력 0 · 무효 0☐

driver_alive가 0이 아니면 어딘가에 발사기 창이 남아 있다. 그 창에서 Ctrl+C를 누르면 세션이 1초 안에 끝난다(15화).

지난 리포트의 재측정 칸을 연다. 15화 T3 2호 12번 ①: rev01 운영 적용 · 운영 소요를 다시 잰다 · 오과장 · 6/17. 운영 로그는 6/17 10:00 → 10:07, 6/24 10:00 → 10:06이다. 이 줄은 STEP 10의 T8 ⑨에서 닫는다.


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

Q1. 3세션이 생각 시간 없이 9분 동안 돌면, 리포트 머리의 DB Time 은 몇 분일까?          ______
Q2. 그 구간의 Buffer Hit % 는? 그리고 DB Time 중 I/O 를 기다린 몫은?                  ______ / ______
Q3. CPU 가 꽉 찼다면, CPU 를 두 배로 늘렸을 때 DB Time 은 최대 몇 % 줄까?              ______
Q4. SQL ordered by Elapsed · CPU · Gets · Executions 의 1위는 같은 SQL 일까?           예 / 아니오
Q5. 보정 배치 rev00 이 정산 한 건에 부른 세 문장(각 10만 번)은 Executions 목록에 몇 개 나올까?  ______
Q6. 보정 배치를 rev00 → rev01 로 바꾸면 그 구간의 DB Time 은 얼마나 줄까?               ______
▶ 적고 나서 펼치기
  • Q1: 28.08분(평균 활성 세션 3.12. 3세션 몫이 3.03이고 나머지는 루트의 스냅샷 세션 등).
  • Q2: Buffer Hit 99.99%. 그런데 DB Time의 11.1%가 쓰기 쪽 I/O를 기다렸다(enq: RO 6.6 · local write wait 3.2 · direct path sync 1.3). 히트율은 쓰기를 세지 않는다.
  • Q3: 약 25%(CPU를 기다린 몫 25.1%). 나머지 64.5%는 일 자체라 그대로다.
  • Q4: 아니오. Elapsed, CPU, Gets는 Q2 rev01이고 Executions는 보정 배치의 INSERT(99,870)다. 그리고 Elapsed 2~4위는 실행 0인 PL/SQL 호출 셋이다.
  • Q5: 1개(INSERT). 등급 조회와 COUNT(*)는 목록에 없다. 목록은 실행 수로 뽑지 않기 때문이다(Captured SQL account for 67.2%).
  • Q6: 줄지 않는다(28.1 → 28.2분 · %Diff 0.4). 대신 초당 실행이 26.6% 준다.

STEP 2 — SOP 1 · 2 · 3: 어디서 보나 · 간격과 보존 · 부하 (10분) ​

bash
MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba < 실습/01_AWR_현황_SYSDBA.sql
확인기대 (교재 실측)☐
[1] CON_NAME · 컨테이너CDB$ROOT · CDB$ROOT · PDB$SEED · FREEPDB1(DBID 셋이 다르다)☐
[2] 팩 · 통계 수준 · PDB 자동 스냅샷DIAGNOSTIC+TUNING · TYPICAL · awr_pdb_autoflush_enabled TRUE (ISDEFAULT TRUE)☐
[2] 간격 · 보존루트 · FREEPDB1 각각 1시간 · 8일☐
[2] 스냅샷루트 자동 · PDB 자동이 같은 시각에 쌓인다(snap_flag 0)☐
[3] SM/AWR수십~100MB 남짓(교재 85.6MB)☐
[4] processes · sessions한계(200 · 322)까지 넉넉하다☐
[4] NUM_CPUS vs cpu_count호스트 CPU 수(교재 32) vs 2: 같지 않다☐

⚠️ sqlp로는 안 된다. DBMS_WORKLOAD_REPOSITORY를 부르면 PLS-00201이 난다. 스냅샷과 리포트는 SYS로 한다. 간격과 보존은 바꾸지 않는다. 구간은 수동 스냅샷(02)으로 잡는다. 바꿔야 한다면 01 [5]의 두 줄을 쓰고, 끝나면 반드시 원래 값으로 되돌린다.

SOP 3: 부하를 정한다. T7 양식(T7_워크로드_프로파일.md)의 1~8번을 연필로 먼저 채운다. 프로파일 ID는 WP-16A. 명령은 STEP 3의 한 줄을 그대로 적는다.


STEP 3 — 구간 A: 부하와 스냅샷 (12분 + 기다림) ★ SOP 4 ~ 7 ​

창 둘을 띄운다. 어느 쪽을 먼저 띄워도 된다. 02는 런을 10분까지 기다린다. 단, 런 시작 뒤 1분 55초 안에 02가 떠 있어야 S1을 놓치지 않는다.

창 1: 발사기(환경 폴더에서)

bash
cd 10_본편_튜너의_1년/00_자료준비/고객사/L1_ora-hanorder
PROFILE=STEADY MINUTES=12 SESSIONS=3 THINK_MS=0 NOTE=C16-A ./05_부하_돌리기.sh
powershell
Set-Location 10_본편_튜너의_1년\00_자료준비\고객사\L1_ora-hanorder
.\05_부하_돌리기.ps1 -LoadProfile STEADY -Minutes 12 -Sessions 3 -ThinkMs 0 -Note C16-A

창 2: 스냅샷(이 화의 폴더에서)

bash
MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba < 실습/02_구간_스냅샷_SYSDBA.sql
powershell
Get-Content 실습\02_구간_스냅샷_SYSDBA.sql -Encoding UTF8 | docker exec -i ora-hanorder sqlplus -s / as sysdba
02의 출력기대 (교재 실측)☐
[4]run N C16-A started … · S1 at +120 s · S2 at +660 s · batch at +240 s☐
[5] S1루트 · PDB 번호 하나씩(번호는 서로 다르다)☐
[6] batch rev00ela 약 230~250cs(교재 232 · 252 · 혼자일 때 214~224) · recursive calls 약 301,500 · adjusted 99850 · returned 0☐
[7] S2 · 구간구간 = S1 시각 + 9분☐
발사기의 출력기대☐
[4] 세션 실행 수 · 에러 · 끝난 이유세션마다 14만 ~ 15만 · 0 · DEADLINE☐
[6] 분별 횟수0~11분이 고르다(Q1 약 1.1만 · Q2 약 1,850 · Q4 약 1.45만 / 분): 정상 상태☐
[8] 원본 지문[1]과 같다☐
[9] 남은 드라이버 세션0☐

STEP 4 — 리포트 한 장 · 9칸 중 ① ~ ⑥ (20분) ★ SOP 8 ​

bash
MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba < 실습/03_AWR_리포트_SYSDBA.sql > awr_A.txt
MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba < 실습/04_9칸_직접_읽기_SYSDBA.sql

awr_A.txt(약 5,200줄)를 편집기로 연다. 처음부터 읽지 않는다. 9칸 순서대로 찾아가서 같은 칸을 04의 출력과 견준다. 두 값이 같다면 리포트의 그 숫자가 어디서 왔는지 아는 것이다.

칸리포트에서 찾을 줄기대 (교재 실측 · 구간 A)☐
①Elapsed: · DB Time:9.00 · 28.08 (mins)(둘째 판 28.05) → 평균 활성 세션 3.12☐
②Load ProfileLogical read 약 27만 / 초 · Physical read 약 38 · Physical write 약 3,475 · Executes 약 2,113☐
③Instance Efficiency PercentagesBuffer Hit 99.99 · Library Hit 98.05 · Soft Parse 96.17 · Execute to Parse 73.05 · Latch Hit 99.81☐
④Top 10 Foreground EventsDB CPU 64.5 · resmgr:cpu quantum 24.0 · enq: RO - fast object reuse 6.6 · local write wait 3.2 · direct path sync 1.3☐
⑤Host CPU · Instance CPUCPUs 32 · %Idle 92.5 · % of busy CPU for Instance 84.5 · %DB time waiting for CPU 25.1(둘째 판 24.7)☐
⑥Time Model Statisticssql execute 99.9 · DB CPU 64.5 · sequence load elapsed time 92.6(1,561초, 둘째 판 86.7 · 1,460초)☐
☐ ③ 의 비율 옆에 04 [3] 의 '분자 · 분모' 를 적었다 — Buffer Hit 99.99 옆에 physical writes 3,475 / 초
☐ ④ 의 셋째 ~ 다섯째 줄(합 11.1 %)이 전부 '쓰기' 를 기다린 것임을 짚었다 (P1 rev02 의 TRUNCATE + APPEND)
☐ ⑤ 에서 '늘리면 줄어드는 것' 을 한 줄로 적었다 — CPU 를 기다린 25.1 %
☐ ⑥ 의 sequence load 1,561 초를 ⑦ 의 N1 INSERT Elapsed(약 6.6 초)와 견줬다 — 맞지 않는 칸은 결론에 쓰지 않는다

리포트 맨 위의 Top ADDM Findings에 Sequence Usage 92.64가 1위로 떠 있다. 오늘은 적어만 둔다. ADDM은 17화에서 다룬다.


STEP 5 — 9칸 중 ⑦ · ⑧ · ⑨ (20분) ★ 1위는 넷이다 ​

04의 [7] · [8] · [9]와 awr_A.txt의 SQL ordered by …, Segments by Logical Reads를 본다.

⑦ 네 목록의 1위 ​

관점1위 (교재 실측)값 · 실행 · 실행당내 1위☐
ElapsedQ2 rev01663.6초 · 16,525 · 40ms☐
CPUQ2 rev01516.1초 · 31ms☐
GetsQ2 rev0196,414,870 · 5,834.5블록 / 회☐
Executions보정 배치의 INSERT INTO T_STLM_ADJ_C1699,870 · Rows per Exec 1.0☐
☐ Elapsed 2 ~ 4위 — BEGIN PKG_LOAD_DRIVER.RUN_SESSION(n) — Executions 0 · 32 % 씩. 머리말 'includes the resources used by all SQL' 을 읽었다
☐ Captured SQL account for … % (Elapsed 77.4 · Executions 67.2) 를 적었다
☐ 보정 배치의 등급 조회 · COUNT(*) (각 10만 번)가 Executions 목록에 없다 — 목록은 실행 수로 뽑지 않는다 (2_파고들기 §9.3)
☐ Q2 의 실행당 Gets 는 바닥(07화 5,869)이다 — 1위인 이유는 '횟수' 다
☐ P1 은 문장 6개(INSERT 3 · TRUNCATE 3)로 쪼개져 Elapsed 7위 아래로 흩어졌다

실행 수 1위는 Q1 rev03(약 99,000)과 보정 배치 INSERT(99,870) 사이에서 바뀔 수 있다. 장비가 빠르면 9분 동안 Q1이 더 돈다. 둘 다 Rows per Exec 1.0인 싼 문장이라는 판정은 같다.

⑧ 세그먼트 ​

1 ~ 3위 (교재 실측)☐
T_ORD_BIG 66.5% · T_ORD_DET 18.2% · IX_ORD_BIG_DT_AMT 6.2%☐

⑨ 대조 — 부하 발생기가 센 것 vs AWR이 센 것 ​

조각부하 발생기 (교재)AWR (교재)맞나☐
Q1 rev0399,10398,955맞다☐
Q2 rev0116,54416,525맞다☐
Q3 rev0133,11533,080맞다☐
Q4 rev03 (SQL 3)131,801131,644맞다☐
N1 rev0146,12146,076맞다☐
P1 rev02 (SQL 3)3,3542,131빈다(둘째 판 3,419 vs 2,892)☐
☐ P1 의 INSERT 커서가 공유 풀에서 loads · invalidations 가 실행 수만큼 크다 — TRUNCATE 가 매번 무효로 만든다
☐ 보정 배치 기록(02 [6]) recursive calls 약 30만 vs AWR 목록의 INSERT 99,870 — 나머지는 목록 밖

STEP 6 — 구간 B · 두 구간 비교 (15분 + 기다림) ★ ​

STEP 3과 같다. NOTE만 C16-B로 바꾼다(02가 NOTE를 보고 보정 배치를 rev01로 돌린다).

bash
PROFILE=STEADY MINUTES=12 SESSIONS=3 THINK_MS=0 NOTE=C16-B ./05_부하_돌리기.sh          # 창 1 (L1 폴더)
MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba < 실습/02_구간_스냅샷_SYSDBA.sql   # 창 2

끝나면 다음을 돌린다.

bash
MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba < 실습/05_AWR_비교_SYSDBA.sql > awr_diff_AB.txt
MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba < 실습/04_9칸_직접_읽기_SYSDBA.sql
확인기대 (교재 실측)☐
02 [6] batch rev01ela 약 30~40cs(교재 38 · 30 · 혼자 27~28) · recursive calls 약 2,700~2,900 · adjusted 99850 · returned 170☐
비교 리포트 머리: DB time (min)28.1 → 28.2 · %Diff 0.4(둘째 판 28.1 → 28.0 · −0.2)☐
Workload Comparison: Executes (SQL)2,112.6 → 1,550.9 · −26.6(둘째 판 −26.3)☐
〃 Redo size · Block changes−11.9 · −11.9☐
〃 Logical read · Physical write−0.5 · −0.1(같은 부하)☐
04 [3] Execute to Parse %73.05 → 63.28(둘째 판 72.96 → 63.07)☐
☐ '바뀐 것의 자국' (Executes · Redo) 과 '같은 부하였다는 증거' (Logical read · Physical write) 를 나눠 적었다
☐ 보정 배치는 배치에게 6 ~ 8배(232 ~ 252 → 30 ~ 38 cs) · 시스템 DB Time 에는 ±0.4 % — 운영 전체의 느림은 보정 배치가 아니었다
☐ 고쳤더니 Execute to Parse % 가 10 포인트 떨어졌다 — 07화 히트율과 같은 구조

STEP 7 — SQL 하나의 리포트 · 부하 모델의 Q2 (10분) ​

bash
MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba < 실습/06_AWR_SQL_리포트_SYSDBA.sql > awr_sql_A.txt
docker exec -i ora-hanorder sqlplus -s sqlp/sqlp@localhost/FREEPDB1 < 실습/09_부하모델의_Q2.sql
06기대 (교재 실측)☐
첫 줄SQL_ID 8ac5jyu193w2j (ACTION Q2 rev01). SQL_ID는 문장의 해시라 어느 DB에서도 같다☐
Plan StatisticsElapsed 663,575ms · CPU % Snap Total 47.5 · Buffer Gets / 회 5,834.5 · Disk Reads 0☐
Execution PlanVIEW VW_GBC_5가 있다(옵티마이저의 '먼저 묶기', 08화)☐

⚠️ 06은 AWR_SQL_REPORT_TEXT에 일곱째 인자(l_con_dbid = PDB의 DBID)를 준다. 다섯 개만 주면 "No data exists for this section of the report."만 나온다(교재 실측).

09(부하 없이 · 예열 뒤 10번)Buffers / 회CPU(10번 · cs)실행계획☐
1 DRIVER(부하 발생기의 Q2)5,85629~30VW_GBC_5 · plan 77778225☐
2 REV01(운영 Q2 rev01 · 지역명 스칼라)5,868113~116HASH JOIN → HASH GROUP BY · plan 2292855265☐
3 GB_FIRST(08화 보류안)5,86829~32☐
[C] 1 vs 2 등급 · 건수 · 금액MINUS 0 / 0☐
☐ 부하 발생기의 Q2 는 운영 문장이 아니다 — 스칼라 한 줄이 빠져 옵티마이저가 '먼저 묶기' 를 한다
☐ 그래서 1 은 3(보류안)과 같은 값이다. 운영 rev01 은 CPU 를 약 3.9 배 쓴다
☐ T7 9번 「운영과 다른 점」 첫 줄에 적었다 · 08화 재검토 조건 = 충족 (더 단단하게) · 이 화는 고치지 않는다 → 18화

STEP 8 — PDB 레벨 AWR은 어디까지 되나 (5분) ​

bash
MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba < 실습/07_PDB_레벨_AWR_SYSDBA.sql
07기대 (교재 실측)☐
[1] awr_pdb_autoflush_enabled루트 · FREEPDB1 둘 다 TRUE · ISDEFAULT TRUE(개정계획에는 기본값이 false라고 적혀 있다. 이 버전은 다르다)☐
[2] 구간 A의 스냅샷루트 둘 · PDB 둘. 번호가 서로 다르다☐
[2] 루트에서 하나 더 찍은 순간 PDB에 생긴 스냅샷0: 루트의 수동 스냅샷은 루트에만 생긴다☐
[3] sqlp에게 보이는 것DBA_HIST_SQLSTAT · SEG_STAT · CON_SYSSTAT · OSSTAT는 행이 있다 · DBA_HIST_SYSSTAT · SYS_TIME_MODEL은 0 · AWR_REPORT_TEXT는 ORA-00904☐
[4] 리포트 세 가지DB Time 루트 28.08 · PDB 27.30 · 27.30 / Instance Efficiency · Host CPU · Instance CPU는 루트 리포트에만 · 나머지 칸은 셋 다☐
☐ 9칸이 다 있는 리포트는 루트 리포트뿐이다 — 그래서 이 화는 루트에서 뽑는다
☐ PDB 리포트의 DB Time 이 작은 이유를 한 줄로 적었다 (루트의 포그라운드 — SYS · 스냅샷 · 리포트 세션 — 는 PDB 의 몫이 아니다)

STEP 9 — (선택) 한 시간: 리포트 한 장의 결론 (62분 + 15분) ★ 17화가 다시 연다 ​

17화에서 같은 인자로 같은 런을 다시 만든다. 오늘은 이 한 시간을 AWR 리포트 한 장으로만 읽고 결론을 적는다. 인자의 뜻은 묻지 않는다. 무엇이 들었는지는 17화에서 연다.

창 1

bash
PROFILE=SPIKE MINUTES=62 SESSIONS=3 THINK_MS=0 SPIKE_AT=31 SPIKE_LEN=5 SPIKE_KIND=LOCK HOLD_SEC=10 SEED=15 NOTE=C16-H ./05_부하_돌리기.sh
powershell
.\05_부하_돌리기.ps1 -LoadProfile SPIKE -Minutes 62 -Sessions 3 -ThinkMs 0 -SpikeAt 31 -SpikeLen 5 -SpikeKind LOCK -HoldSec 10 -Seed 15 -Note C16-H

창 2(02가 NOTE를 보고 +1분과 +61분에 찍는다)

bash
MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba < 실습/02_구간_스냅샷_SYSDBA.sql

끝나면(리포트 파일은 03을 그대로 흘려 보내며 이름만 바꾼다)

bash
sed 's/C16-A/C16-H/' 실습/03_AWR_리포트_SYSDBA.sql | MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba > awr_H.txt
MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba < 실습/04_9칸_직접_읽기_SYSDBA.sql
powershell
(Get-Content 실습\03_AWR_리포트_SYSDBA.sql -Encoding UTF8) -replace 'C16-A','C16-H' | docker exec -i ora-hanorder sqlplus -s / as sysdba > awr_H.txt

창 1의 발사기 출력([6] 분별 횟수 · [7] ASH)은 읽지 않는다. 운영팀에는 그런 기록이 없다. 정각마다 찍힌 AWR 한 장뿐이다. awr_H.txt 뒤쪽의 Active Session History (ASH) Report와 ADDM Reports 절도 오늘은 열지 않는다(17화). 04는 구간 H를 대조(⑨)하지 않는다.

칸기대 (교재 실측 · 구간 H 60분)☐
①Elapsed 60.00 · DB Time 181.09분 · 평균 활성 세션 3.02 · DB CPU 1.84초/초☐
②logical read 약 25만 / 초 · physical write 약 3,165 · executes 약 1,416☐
③Buffer Hit 99.99 · Execute to Parse 63.38☐
④DB CPU 61.0 · resmgr 23.0 · enq: RO 6.0 · enq: TX - row lock contention 5.5%(약 600초 · 853 waits · 평균 약 700ms) · local write 2.9 · direct path sync 1.2☐
⑤%DB time waiting for CPU 23.8☐
⑥sequence load 약 9,700초(89%): 여전히 맞지 않는 칸☐
⑦네 목록의 1위는 구간 A와 같은 얼굴 · FOR UPDATE 문장은 목록에 없다 · Captured SQL 66.5%☐
⑧Segments by Row Lock Waits: SYS.OPTSTAT_HIST_CONTROL$ 930(87.82%) · SQLP.T_STLM_NUM_LD 129(12.18%)☐

결론을 적는다. 9칸의 순서대로, 칸마다 근거를 붙여서 T5-001의 3번과 8번에 쓴다. 교재의 결론은 2_파고들기 §14.3에 있다. 자기 결론을 먼저 쓰고 나서 펼쳐 본다.

☐ 결론을 적었다 — 이 한 시간의 주된 문제 · 부차적인 것 · 이 리포트로 말할 수 없는 것
☐ 조민우 씨의 "6/17 10시 반 몇 분" 이 이 리포트의 어느 칸에 있는지 찾아봤다

이 STEP의 숫자는 지우면 안 된다. T5 1호의 결론으로 남겨 두고, 17화에서 맨 처음 하는 일이 바로 이 결론을 다시 여는 것이다.


STEP 10 — T5 · T7 · T8 1호 ★ 오늘의 산출물 ​

양식: T5_시스템_성능_리포트.md · T7_워크로드_프로파일.md · T8_정기_점검.md

bash
MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba < 실습/08_정기점검_SYSDBA.sql

10-1. T7 워크로드 프로파일 1호 — WP-16A · WP-16B · WP-16H ​

#항목WP-16A · WP-16BWP-16H (선택)
1ID · 목적붐비는 월요일 오전 + 주간 보정 배치 한 판: A = rev00(6/10까지) · B = rev01(6/17부터)운영의 한 시간(10:00 ~ 11:00): 선배가 정한 프로필. 무엇이 들었는지는 17화에서 연다
2대상 · 데이터 · 통계sqlp@FREEPDB1 · T_ORD_BIG 1,000,000 / 255,398,623,700 · 인덱스 3 · ORD_ST FREQUENCY · T_ORD_STLM 100,000 · 통계 STALE 없음 · 보정 배치의 무대 C16(정산 100,020 · 고객 1,997)같다(C16은 쓰지 않는다)
3세션 구성부하 3세션 · WEIGHTS=Q1=30,Q2=5,Q3=10,Q4=40,N1=14,P1=1(기본값) · +4분에 보정 배치 1판(sqlp 별도 세션 · MODULE = ADJ_BATCH)부하 3세션 · 같은 가중치 · PROFILE=SPIKE SPIKE_AT=31 SPIKE_LEN=5 SPIKE_KIND=LOCK HOLD_SEC=10
4시간 구성데우기 2분 · 구간 9분(+2:00 ~ +11:00) · 꼬리 1분 · 런 12분 · THINK_MS 0: CPU 2개를 넘치게 해서 줄 서기를 보이려고데우기 1분 · 구간 60분(+1:00 ~ +61:00) · 꼬리 1분 · 런 62분 · THINK_MS 0
5입력값 분포SEED 15(세션 k의 씨앗 15,000 + k) · Q1 36개월 중 하나 · Q4 첫 페이지 30% · 다음 60% · 날짜 10% · N1 고객 2,000 중 하나 · 금액 10,000~500,000같다
6도구 · 명령PROFILE=STEADY MINUTES=12 SESSIONS=3 THINK_MS=0 NOTE=C16-A ./05_부하_돌리기.sh(B는 NOTE=C16-B) + 02_구간_스냅샷_SYSDBA.sqlPROFILE=SPIKE MINUTES=62 SESSIONS=3 THINK_MS=0 SPIKE_AT=31 SPIKE_LEN=5 SPIKE_KIND=LOCK HOLD_SEC=10 SEED=15 NOTE=C16-H ./05_부하_돌리기.sh + 02
7성공 판정V$RESOURCE_LIMIT processes 84 / 200 · sessions 110 / 322 · 에러 0 · 원본 지문 앞 = 뒤 · 남은 세션 0 · 분마다 Q1 약 1.1만 · Q2 약 1,850(고르다)에러 0 · 지문 앞 = 뒤 · 남은 세션 0
8정리 절차END_RUN이 작업 테이블을 비운다 · 99가 C16을 지운다 · 통계 · 스냅샷 간격 · 보존은 바꾸지 않았다 · 남긴 것: AWR 스냅샷 · 런 기록같다
9운영과 다른 점 ★① Q2의 문장: 지역명 스칼라가 없어 실행계획이 VW_GBC · 실행당 CPU가 운영 rev01의 약 1/4(09) → 이 리포트의 Q2 CPU 몫은 운영보다 작다 ② P1의 빈도: 운영은 밤에 한 번 · 이 모델은 9분에 3,354번 → ④의 쓰기 I/O 11.1%는 모델의 사실 ③ 생각 시간 0: 실행 빈도가 압축돼 있다 · 초당 실행 수를 운영과 견주지 않는다 ④ 정산 10만 건: 보정 배치는 2초 남짓(운영은 수 분) ⑤ CPU 2(Free) ⑥ N1 · P1은 원본이 아니라 *_LD 작업 테이블에 쓴다왼쪽과 같다 + 무엇이 들었는지 모른 채 읽는다(운영처럼)
10이 프로파일로 낸 리포트T5-001 6번 (A vs B 비교)T5-001

10-2. T5 시스템 성능 리포트 1호 — T5-001 ​

STEP 9를 하지 않았다면 1번과 3번을 구간 A로 쓴다(값은 STEP 4 · 5). 아래는 교재의 1호(구간 H)다.

1. 구간

항목값
컨테이너 · 리포트CDB$ROOT 리포트(루트 스냅샷) · 03을 C16-H로
스냅샷런 +1:00(S1) · +61:00(S2): 교재 19 · 21(사이에 정각 자동 스냅샷 20) · 번호는 런마다 다르다
Elapsed · DB Time · 평균 활성 세션60.00분 · 181.09분 · 3.02
cpu_count · 호스트2 · 32 CPU(16코어)
구간 안의 사건(모른다. 리포트로만 읽었다)

2. 워크로드 프로파일: WP-16H(T7-001) · 운영과 다른 점: T7 9번 ①~⑥

3. 9칸

#칸무엇을 의심했나무엇으로 확인했나결론
①머리얼마나 바빴나DB Time ÷ Elapsed = 3.02 · cpu_count 2CPU 2개에 평균 3명. 1명 남짓은 늘 기다린다
②Load Profile무슨 일을logical 251,864.8 · physical read 34.7 · write 3,165.3 · executes 1,415.7 / 초읽기는 전부 캐시 · 쓰기가 읽기의 90배
③Instance Efficiency ⚠️(결론에 쓰지 않는다)Buffer Hit 99.99 옆에 physical writes 3,165 / 초 · Execute to Parse 63.38히트율은 쓰기와 direct path를 세지 않는다 · 낭비가 줄면 비율이 떨어질 수 있다(A → B의 73.05 → 63.28)
④Top FG Events시간이 어디로DB CPU 61.0 · resmgr 23.0 · enq: RO 6.0 · enq: TX 5.5 · local write 2.9 · direct path sync 1.2CPU와 CPU 차례가 84% · 쓰기 대기 10.1% · 행 락 5.5%(853번 · 평균 702ms)
⑤Host · Instance CPU늘리면 무엇이 줄어드나%DB time waiting for CPU 23.8 · Host %Busy 7.0CPU를 늘려 줄어드는 최대치 23.8% · 호스트는 남는다
⑥Time Model일의 종류sql execute 10,859.8 · sequence load 9,676.7(89%)sequence load는 ⑦의 SQL과 맞지 않는다(구간 A: 1,561초 vs 그 SQL 6.6초). 결론에 쓰지 않는다
⑦SQL 4관점누가Elapsed · CPU · Gets 1위 Q2 rev01(4,000.5초 · 102,398번 · 실행당 5,835블록) · Executions 1위 Q1 611,986 · 실행 0인 PL/SQL 셋 · Captured 66.5%Q2는 실행당 바닥 · 1위는 횟수 · 락을 기다린 SQL은 목록에 없다
⑧Segments어디서Logical Reads T_ORD_BIG 66.8% / Row Lock Waits SYS.OPTSTAT_HIST_CONTROL$ 87.82% · T_STLM_NUM_LD 12.18%행 락은 대부분 통계 테이블(P1의 온라인 통계) · 일부 채번 작업 테이블
⑨대조—하지 않았다(운영처럼 리포트 한 장으로)—

4. 【17화】 ADDM: 리포트 머리에 Sequence Usage 96.63 · 88.06 · Top SQL Statements · Resource Manager CPU Throttling이 있다. 검토하지 않았다. 1위의 근거 줄(⑥)이 맞지 않는 칸이라는 것만 적어 둔다.

5. 【17화】 구간 안의 시간 분포. 이 리포트로 말할 수 없는 것: enq: TX 853번, 599초가 언제였나 · 누가 그 행을 쥐었나 · 조민우 씨의 "6/17 10시 반 몇 분".

6. 개선 전후 비교(구간 A → B · 05)

항목A (보정 rev00)B (보정 rev01)%Diff해석
DB time (분)28.128.20.4시스템 전체는 그대로
보정 배치 경과(02 [6])232cs38cs배치 자체는 6배
Executes / 초 · Redo / 초2,112.6 · 773,7471,550.9 · 681,451−26.6 · −11.9바뀐 것의 자국
Logical read · Physical write / 초272,105.0 · 3,475.2270,705.7 · 3,472.1−0.5 · −0.1같은 부하였다
Execute to Parse %73.0563.28고쳤더니 비율이 떨어졌다

7. 팩 라이선스: Oracle AI Database 26ai Free · CONTROL_MANAGEMENT_PACK_ACCESS = DIAGNOSTIC+TUNING · Free에는 진단 · 튜닝 팩이 들어 있다(EE는 별도 구매, 계약 없는 EE에서는 이 리포트를 뽑지 않는다)

8. 결론과 다음 행동

#후보근거다음 절차검증리스크
1Q2: 횟수 · 08화 보류안⑦ CPU 1위 · 실행당 바닥 · 09(운영 문장은 CPU 3.9배)현업에 '등급별 매출 화면의 새로 고침 주기' 확인 · 보류안은 T1 + 정합성 체크리스트 → 18화같은 프로파일로 재현 · 05로 비교모델의 Q2가 운영 문장과 다르다(T7 ⑨)
2CPU 증설⑤ 23.8%(구간 A 25.1%)증설 회의에 '최대 4분의 1'을 가져간다—일의 양이 그대로면 줄만 짧아진다
3P1의 쓰기 대기 10%④ · T7 ⑨ ②조치 없음: 모델의 왜곡(운영 P1은 밤에 한 번 · T3로 본다)——
4행 락 5.5%④ · ⑧부차적: 한 번에 1초 미만 · 대부분 통계 테이블(17화)—

9. 정합성 회귀: 해당 없음. 이 화에서는 SQL을 한 줄도 고치지 않았다(진단만 했다). 보정 배치는 15화의 두 판을 C16 복사본에서 그대로 돌렸다. 보정 99,850 · 반송 0(rev00) / 99,850 · 170(rev01)으로 15화와 같다.

10-3. T8 정기 점검 1호 — 6월 24일 ​

비교 기준: 지난주 = 구간 A(보정 rev00) · 이번 주 = 구간 B(보정 rev01). 같은 부하로 9분씩 쟀다(연습 DB). 운영이라면 같은 요일, 같은 시각의 자동 스냅샷 두 쌍이다.

일간 5칸

#칸지난번 (A)이번 (B)움직임원인을 물을까
①Top 5 FG EventsDB CPU 64.5 · resmgr 24.0 · enq: RO 6.6 · local write 3.2 · direct path sync 1.364.3 · 24.5 · 6.4 · 3.1 · 1.2(순위 같음)±1아니오
②DB Time 추세(평균 활성 세션)3.123.13같다아니오. 단, 둘 다 cpu_count 2를 넘는다(늘 1명이 기다린다)
③새로 들어온 · 빠진 Top SQL—새 얼굴: P1의 INSERT 하나가 Elapsed 8위로(같은 조각의 문장끼리 자리를 바꿨다) · 빠진 얼굴: 보정 배치 rev00의 INSERT(A의 Executions 1위)보정 배치 교체의 자국아니오(설명됨)
④배치 소요 vs 마감보정 rev00 · 연습 DB 부하 위 232cs · 운영 6/10 10:00 → 10:49(여유 11분)보정 rev01 · 38cs · 운영 6/17 10:00 → 10:07 · 6/24 10:00 → 10:06(여유 53~54분)여유 +42분아니오(T3-002 ① 완료)
⑤세그먼트 · 저장소T_ORD_BIG 6,016블록 · 인덱스 셋 3,456 · 3,328 · 2,816 · SM/AWR 85.6MB(16화 시작)같다 · SM/AWR 101.1MB · 휴지통 22개 · 133.1MB(LOB 하나 130.3MB)AWR +15.5MB / 하루 · 휴지통예: 휴지통(15화 DBMS_HPROF 결과 테이블을 다시 만들며 남긴 것)

주간 4칸

#칸확인결과조치
⑥인덱스 사용08 ⑥: DBA_INDEX_USAGE · 구간 A의 AWR 실행계획IX_ORD_BIG_DT: 구간 A의 실행계획 0 · 마지막 사용은 이 화의 부하보다 앞 / IX_ORD_BIG_DT_AMT 880,972 · IX_ORD_BIG_DT_SEQ 2,697,749 · PK_T_ITM_EVL 287,939회T2-002 선결 조건 하나를 채웠다(부하 모델의 SQL 안에서만) · 운영 SQL 전수 조사는 남음 → 18화
⑦통계 신선도08 ⑦원본 7개 STALE_STATS NO · ORD_ST FREQUENCY 3버킷 그대로없음
⑧힌트 유효기간 대장3번 행(Q2 rev01 · 해시 자율선택)의 조건M_CUS 2,000(조건 20,000 초과) · pga_aggregate_target 512M(변경 없음) · 6개월(06화부터, 아직)걸린 것 없음
⑨재측정 기한리포트들의 12번 · 재검토 조건T3-002 ① rev01 운영 소요(6/17): 수신 · 닫음 / 08화 Q2 보류안(16화): 조건 충족 / T2-002 선결 조건: 일부Q2 → 18화 · T2-002 → 18화

이번 점검에서 연 티켓

#무엇근거 칸담당기한
1SQLP 휴지통 정리: PURGE 전에 무엇인지 확인(15화 HPROF 흔적 130MB)⑤나다음 점검 전
2등급별 매출 집계 화면의 새로 고침 주기(Q2의 횟수)③ · T5-001 8번 ①조민우 · 개발팀금요일 증설 회의 전
36/17 10시 반 정산 등록 '몇 분'(조민우) · T5-001 5번나17화

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

박팀장에게 보낼 회신을 쓴다. "히트율은 초록불, CPU는 100%. CPU를 늘리자는데, 보정 배치도 고쳤다면서 왜 전체가 느린가." 금요일 증설 회의에 그대로 들고 갈 수 있게 쓴다.

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

① 운영팀이 틀렸다고 쓰지 않는다. 히트율 99점대도, CPU 100%도 사실이다. 틀린 것은 그 한 칸에서 낸 결론이다. 첫 문장은 "그 숫자는 사실이지만, 그 숫자만으로는 보이지 않는 것이 있습니다"이다.

② 증설 회의에는 숫자 하나를 들고 간다. "CPU를 늘려 줄일 수 있는 최대치는 DB 시간의 4분의 1입니다." 나머지 4분의 3은 일 자체이고, 그 일의 절반 가까이를 SQL 하나가 쓴다. 그 SQL은 한 번에 읽는 양이 이미 최소라 '횟수'를 물어야 한다.

③ 연습 DB의 숫자를 운영의 숫자로 쓰지 않는다. 연습 DB는 CPU가 2개이고, 부하는 우리가 만든 모델이다(T7). "같은 구조라면 이런 모양이 나옵니다"까지만 쓴다. 특히 부하 모델의 Q2가 운영 문장과 다르다는 것은 숨기지 않는다.

④ 보정 배치는 '실패'가 아니다. 배치는 6배 빨라졌고 반송함이 생겼다. 시스템 전체가 느린 원인이 거기 있지 않았을 뿐이다. 둘을 섞으면 다음 주에 "고쳐도 소용없다"는 말이 돈다.


STEP 12 — 파인만 자가설명 ​

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

태그전형적인 문장
#인과"9분 구간에 DB Time이 28분인 이유를 말로 못 하겠다" → §4
#용어"resmgr:cpu quantum과 DB CPU가 어떻게 다른지 설명하다 막혔다" → §7
#수치"Executions 목록에 10만 번 돈 문장이 왜 없는지 숫자로 못 보이겠다" → §9.3

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

  1. 조건 반전: "생각 시간을 200ms로 두면(15화 기본값) 오늘의 세 판정 중 무엇이 뒤집히나?"
  2. 반례 요구: "히트율로 정말 I/O 문제를 알 수 있는 경우를 하나 든다면? 그때도 옆에 무엇을 둬야 하나?"
  3. 측정 지목: "'CPU를 늘려도 25%만 준다'를 반증하려면 어떤 숫자가 필요한가? Free에서는 왜 그걸 못 재나?"

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


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

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

기대: driver_alive 0 · c16_left 0 · 1000000 · 3 · FREQUENCY · 100000 · 0 · VALID · VALID · 3 · 원본 지문이 STEP 0과 같다 · 런 기록 C16-A · C16-B(· C16-H)가 남아 있다.

남기는 것: AWR 스냅샷(보존 8일)과 부하 발생기의 런 기록. 17화에서 구간 H를 다시 연다. 스냅샷 간격과 보존은 이 화에서 바꾸지 않았으니 되돌릴 것이 없다(01 [2]의 1시간 · 8일 그대로).


완료 체크리스트 ​

  • [ ] STEP 0: 전제, 원본 지문, 지난 리포트의 기한(T3-002 ①)을 확인했다
  • [ ] STEP 1: 보기 전에 예측 6개를 적었다
  • [ ] STEP 2: 루트에서 본다는 것과 팩, 간격, 보존, NUM_CPUS vs cpu_count를 확인했다
  • [ ] STEP 3: 구간 A를 창 둘로 찍었다 · 에러 0 · 지문 불변 · 남은 세션 0
  • [ ] STEP 4: 리포트의 ①~⑥이 04와 같은 값인지 확인했다 · 히트율 옆에 쓰기 · CPU를 늘리면 줄어드는 몫
  • [ ] STEP 5: 네 목록의 1위를 나란히 적었다 · 목록 밖의 실행(Captured %) · ⑨에서 P1이 빈 이유
  • [ ] STEP 6: 구간 B와 겹쳤다 · DB Time 0.4% · Executes −26.6% · Execute to Parse % 하락
  • [ ] STEP 7: SQL 리포트의 VW_GBC_5와, 부하 모델의 Q2가 운영 문장과 다르다는 것을 쟀다
  • [ ] STEP 8: PDB 리포트에 없는 칸을 확인했다
  • [ ] STEP 9: (선택) 한 시간 리포트로 결론을 적었다
  • [ ] STEP 10: T5 · T7 · T8 1호를 쓰고 T5의 프로파일 ID 칸, T7의 '운영과 다른 점', T8의 ⑥ ⑨를 채웠다
  • [ ] STEP 12: 막힘 태그 최소 1개를 _막힘로그.md에 옮겼다
  • [ ] 정리: 99로 15화 종료 상태를 확인했다

완결성 게이트: STEP 5의 네 목록 표, STEP 10의 T5 2번(프로파일 ID)과 T7 9번(운영과 다른 점)이 비면 이 화는 미완성이다.


다음 화로 넘기는 상태 ​

무엇값
ora-hanorder 원본변화 없음: 15화 종료 상태(T_ORD_BIG 인덱스 3 · ORD_ST 히스토그램 · T_ORD_STLM 10만 · T_STLM_NUM 0 · PKG_ORD_STLM 원본 · PKG_LOAD_DRIVER VALID · C16 0)
남긴 것AWR 스냅샷(구간 A · B · H, 루트와 PDB) · 부하 발생기 런 기록(NOTE C16-A · C16-B · C16-H)
리비전없다: 이 화에서는 SQL을 고치지 않았다(진단만)
새 양식T5 시스템 성능 리포트 · T7 워크로드 프로파일 · T8 정기 점검(제정 · 각 1호)
열어 둔 것한 시간 평균의 결론: 시간 축으로 → 17화 · ADDM Sequence Usage → 17화 · Q2 보류안 · T2-002 → 18화

다음 → 17화 「평균은 거짓말을 한다」: 오늘 리포트 한 장으로 낸 한 시간의 결론을, 같은 런을 다시 만들어 시간 축으로 펼친다.