테마
T5 — 시스템 성능 리포트 (템플릿)
16화에 제정하고 17화에 개정했다(2호). 시스템 전체(한 인스턴스의 한 구간)를 진단할 때 쓴다. AWR 리포트 한 장을 근거로 삼는다. T1이 "이 SQL 한 번이 몇 블록을 읽는가"를, T3이 "이 배치가 창 안에 끝나는가"를 묻는다면, T5는 "이 구간 동안 이 DB의 시간은 어디로 갔는가"를 묻는다. T5는 처방전이 아니라 진단서다. 여기서 나온 후보는 T1, T2, T3의 절차를 밟아야 실제로 바꿀 수 있다.
왜 이 문서가 있는가
운영팀 대시보드 히트율 99.6% · CPU 100%
운영팀 의견 "I/O 는 문제없다. CPU 가 모자라니 CPU 를 늘리자"
개발팀 의견 "Top SQL 1위를 고치면 된다"16화(6월 24일)에 같은 부하를 연습 DB에 재현해 AWR을 열어 보니, 세 의견 모두 한 칸만 보고 내린 결론이었다.
16화 실측 (ora-hanorder · 9분 구간 · 3세션 · THINK_MS 0) | 그 칸 | 다른 칸에서 본 것 |
|---|---|---|
| "I/O는 문제없다" | Buffer Hit 99.99% | DB Time의 11.1%가 쓰기 쪽 I/O를 기다렸다(enq: RO 6.6 · local write wait 3.2 · direct path sync 1.3). 히트율은 버퍼 캐시를 거친 읽기만 센다 |
| "CPU를 늘리자" | DB CPU 2.01초/초 = cpu_count 2 | DB Time 가운데 CPU를 기다린 몫은 25.1%. CPU를 늘려서 줄일 수 있는 것은 이 줄뿐이다. 나머지 64.5%는 일 자체 |
| "1위를 고치면 된다" | Elapsed 1위 Q2 rev01 663.6초 | Q2는 실행당 5,834블록으로 이미 바닥이다(07화). 1위가 된 것은 16,525번 호출됐기 때문이다. 게다가 Executions 1위는 다른 문장이고, Elapsed 2~4위는 실행 0번인 PL/SQL 호출 셋이다 |
AWR 리포트의 한 칸은 결론이 아니다. 다른 칸에서도 같은 사실이 확인될 때까지 대조한다.
작성 규칙
| 구간을 먼저 적는다 | 스냅샷 두 개의 번호 · 시각 · 컨테이너(루트 / PDB). 구간이 다르면 다른 리포트다 |
| 워크로드 프로파일 ID가 없으면 무효 | T7의 ID를 적는다. 운영 구간이면 "운영 · 프로파일 없음: 그 시간대의 업무"를 적는다 |
| 9칸을 정해진 순서로 읽는다 | 아래 3번 칸. 건너뛴 칸에는 '건너뜀'과 이유를 적는다 |
| 칸마다 세 열을 채운다 | [무엇을 의심했나 → 무엇으로 확인했나 → 결론]. 확인 열에는 리포트의 칸 이름 또는 DBA_HIST_* 쿼리를 적는다 |
| 비율 옆에는 분자와 분모를 적는다 | 히트율이나 Execute to Parse % 같은 비율만 쓰지 않는다(07화). 초당 절대량을 같이 적는다 |
| 맞지 않는 칸을 숨기지 않는다 | 두 칸이 어긋나면 그 사실을 적고, 어긋난 칸으로는 결론을 내지 않는다(16화: Time Model 한 줄) |
| 평균이라는 것을 적는다 | 이 리포트의 모든 숫자는 구간 전체의 평균이다. 구간 안의 '언제'는 이 리포트에 나오지 않으므로 5번 칸에서 본다 |
| SQL을 고치지 않았으면 회귀 검증은 '해당 없음' | 고쳤으면 정합성 회귀 체크리스트를 붙인다(08화 이후) |
양식
┌──────────────────────────────────────────────────────────────────────────────┐
│ T5 시스템 성능 리포트 — N호 문서번호 T5-___ │
├──────────────────────────────────────────────────────────────────────────────┤
│ 작성자 : ____________ 작성일 : __________ 대상 : ______________________ │
└──────────────────────────────────────────────────────────────────────────────┘1. 구간 ★
| 항목 | 값 |
|---|---|
| 컨테이너 · 리포트 종류 | CDB$ROOT 리포트 / PDB 리포트(PDB 스냅샷) / PDB 리포트(루트 스냅샷) |
| DBID · 스냅샷 (S1 · S2) · 시각 | |
| Elapsed · DB Time · 평균 활성 세션 (DB Time ÷ Elapsed) | |
cpu_count · 호스트 CPU | |
| 구간 안의 사건(배치 · 배포 · 장애)과 그 시각 |
2. 워크로드 프로파일 ★ — 비면 무효
| 항목 | 값 |
|---|---|
| 프로파일 ID (T7) | |
| 운영과 다른 점 (T7 9번에서 옮긴다) |
3. 9칸 — 정해진 순서로
| # | 칸 | 무엇을 의심했나 | 무엇으로 확인했나 (리포트 칸 · DBA_HIST_*) | 결론 |
|---|---|---|---|---|
| ① | 머리: Elapsed · DB Time | 얼마나 바빴나 | DB Time ÷ Elapsed vs cpu_count | |
| ② | Load Profile | 초당 무슨 일을 얼마나 | logical / physical read · write · redo · executes · hard parses · commits | |
| ③ | Instance Efficiency ⚠️ | (읽되 결론에 쓰지 않는다) | 비율마다 분자 · 분모의 초당 값을 옆에 적는다 | 히트율 함정 주석 필수. 비율로는 일의 양을 알 수 없다. 낭비가 줄면 오히려 떨어진다(07화 · 16화 Execute to Parse %) |
| ④ | Top 10 Foreground Events | 시간이 어디로 갔나 | DB CPU · 대기 이벤트의 % DB time · 평균 대기 | |
| ⑤ | Host CPU · Instance CPU | CPU는 누구 것인가 | 호스트 %Busy · 인스턴스 몫 · %DB time waiting for CPU | |
| ⑥ | Time Model | DB Time을 일의 종류로 나누면 | sql execute · parse · PL/SQL (줄끼리 겹치므로 더하지 않는다) | |
| ⑦ | SQL ordered by: Elapsed · CPU · Gets · Executions | 누가 | 네 목록의 1위를 나란히 · Captured SQL account for … % · 실행 0인 PL/SQL 호출 · SQL_ID가 쪼개진 일 | |
| ⑧ | Segments by Logical Reads | 어디서 | 상위 세그먼트 · % of Total | |
| ⑨ | 대조: 아는 것과 맞춰 본다 | 리포트가 부하를 제대로 담았나 | 부하 기록 · 배치 로그 · 앱 로그의 횟수와 시각 vs ⑦ · ④ | 맞지 않는 줄과 그 이유 |
4. ADDM 권고와 채택 · 기각 사유 (17화 개정)
| Finding · Impact (평균 활성 세션 · %) | Recommendation | Rationale에 적힌 사실 | ASH로 다시 센 값 (V$ACTIVE_SESSION_HISTORY · DBA_HIST_ACTIVE_SESS_HISTORY) | 채택 / 기각 · 사유 |
|---|---|---|---|---|
권고는 가설이다. Rationale의 사실을 ASH로 다시 센다. 지목된 세션, SQL, 객체가 표본에도 그렇게 찍혔는지, Impact가 표본의 몫과 맞는지 본다. Rationale이 없는 Finding은 그 Finding이 기댄 칸(시간 모델 · 대기 이벤트)을 3번에서 대조한다. 맞지 않으면 기각하고 이유를 쓴다. ADDM의 Impact도 구간 평균이다. 그 몫이 언제 몰렸는지는 5번에서 본다.
5. 구간 안의 시간 분포 — 평균이 가린 것 (17화 개정)
| 항목 | 값 |
|---|---|
| 창 | 분 단위 · 5분 창(운영 시계로 적는다). 한 칸(구간 전체)과 나란히 놓는다 |
| 표본 | 메모리 1초 표본(표본 1건 ≈ DB Time 1초) / 디스크 10초 표본(1건 ≈ 10초). 어느 쪽인지 적는다 |
| 폭발이 있었나 | 그 창의 평균 활성 세션 · 이벤트 몫 vs 구간 전체의 값 |
| 블로킹 체인 | BLOCKING_SESSION · BLOCKING_SESSION_SERIAL# → 누구인가(막은 쪽이 쉬고 있었으면 표본에 없고 이름만 남는다) |
| 그것을 보는 도구 | ASH 직접 조회 · ASH_REPORT_TEXT(ashrpt) · 팩이 없는 현장에서는 Statspack 스냅샷 간격을 좁히거나 블로킹 트리를 주기적으로 찍는다 |
6. 개선 전후 비교 (AWR_DIFF_REPORT_TEXT · awrddrpt)
| 항목 | 첫 구간 | 둘째 구간 | %Diff | 해석 |
|---|---|---|---|---|
| DB Time · 평균 활성 세션 | ||||
| 바뀐 것이 남긴 자국 (Executes · Redo · 해당 SQL) | ||||
| 바뀌지 않아야 할 것 (같은 부하인가) |
7. 팩 라이선스 확인란 ★
| 항목 | 값 |
|---|---|
| 에디션 | |
CONTROL_MANAGEMENT_PACK_ACCESS | |
| 계약 여부 | Free는 진단 · 튜닝 팩 포함 / EE는 별도 구매. 계약 없이 EE에서 AWR 리포트를 뽑으면 위반이다 |
| 팩이 없으면 | NONE이어야 한다. AWR · ASH · ADDM · SQL Monitor 대신 Statspack을 쓴다. 같은 9칸 순서로 읽되 ASH 칸(5번)은 스냅샷 간격으로 대신한다(17화 · 진단도구 4열 대응표) |
8. 결론과 다음 행동
| # | 후보 | 근거 (3번의 칸) | 다음 절차 (T1 · T2 · T3) | 검증 방법 | 리스크 |
|---|---|---|---|---|---|
9. 정합성 회귀
SQL을 고쳤으면 정합성 회귀 체크리스트의 A~H를 붙인다. 고치지 않았으면 "해당 없음: 이유"를 쓴다.
금지어
"히트율이 높으니 I/O는 괜찮다": 히트율로는 I/O의 양을 알 수 없다. 물리 읽기 · 쓰기의 초당 값과 I/O 대기의 % DB time으로 쓴다. "CPU 100%니 CPU를 늘리자": CPU를 늘려서 줄어드는 것은 CPU를 기다린 시간뿐이다. 그 줄의 % DB time을 먼저 적는다. "1위 SQL이 범인이다": 네 목록의 1위를 나란히 적기 전에는 쓰지 않는다. 1위의 실행당 값과 실행 수를 나눠 쓴다.
자매 문서
- T1 단건 SQL 튜닝 리포트: 02화 제정
- T3 배치 SLA 리포트: 14화 제정
- T7 워크로드 프로파일: 16화 제정(T5 2번 칸이 가리키는 문서)
- T8 정기 점검: 16화 제정
개정 이력: 16화에 제정했다(1호 = 연습 DB 재현 · 구간 A 9분 + 구간 H 60분). 17화에 개정해 4·5번 칸의 쓰는 법과 7번 '팩이 없으면'을 더했고, 2호(T5-002 교차검증판 = 1호의 정정)를 냈다.
18화 3호는 T5-003이다. awrddrpt(두 구간 비교 · 같은 날 연달아)로 냈고, 1번 칸에 '무엇과 무엇의 비교인가'를 먼저 적었으며, 시간 모델 1위 줄을 결론에서 빼고 판정했다(사내 튜닝 표준 제1조).