테마
T2 — 인덱스·힌트 변경 승인서 (템플릿)
04화에 제정하고 14화에 개정했다(「3-2 적재 비용」 칸 신설). 인덱스를 만들거나 지우기 전에, 그리고 힌트를 붙이거나 떼기 전에 채운다.
이 양식이 왜 생겼나
2년 전 어떤 보고서에 이렇게만 적혀 있었다.
"3. 조치 : 월마감 집계 쿼리를
ORD_DT선두 인덱스 RANGE SCAN으로 변경 완료"그때 그 결정은 옳았다. 하지만 수치가 없어서 2년 뒤 그 결정이 왜 틀어졌는지 아무도 알 수 없었다. T2는 "무엇을 했는가"가 아니라 "무엇을 재고 했는가"를 남기는 양식이다.
작성 규칙
| T0 측정규약을 따른다 | "빨라졌다"는 쓰지 않는다. Buffers N → M으로만 쓴다 |
| 빈칸은 반려 사유다 | 특히 3·6·7번 칸 |
| 인덱스를 만들기 전에 쓴다 | 만들고 나서 쓰는 건 보고서지 승인서가 아니다 |
| 힌트도 이 양식을 쓴다 | 힌트는 "인덱스를 코드에 박아 넣는 것"이다. 되돌리기가 더 어렵다 |
양식
┌────────────────────────────────────────────────────────────────────────────┐
│ T2 인덱스·힌트 변경 승인서 문서번호 T2-____ │
├────────────────────────────────────────────────────────────────────────────┤
│ 작성자 : ____________ 작성일 : __________ 적용 예정 : __________ │
│ 승인자 : ____________ 승인일 : __________ │
└────────────────────────────────────────────────────────────────────────────┘1. 대상 객체와 제안 정의
| 항목 | 내용 |
|---|---|
| 대상 테이블 | |
| 제안 DDL | CREATE INDEX ... ON ...( ... ) INVISIBLE; |
| 현재 그 테이블의 인덱스 목록 | (개수 · 각각의 LEAF_BLOCKS · CLUSTERING_FACTOR) |
| 컬럼 순서 근거 ★ | 등치 조건 컬럼 선두 / 선택도 / CF / 정렬 대체 여부 중 무엇으로 정했는가 |
| 접두 중복 여부 ★ | 이미 있는 인덱스의 선두 컬럼과 겹치는가. 겹치면 어느 쪽을 지울 것인가 |
2. 기대 이득 — 영향 SQL과 각각의 Buffers Δ
| SQL / 리비전 | 조회 범위(행수·선택도) | 전 | 후 | 측정 방법 |
|---|---|---|---|---|
GATHER_PLAN_STATISTICS + DISPLAY_CURSOR |
범위를 반드시 쓴다. "64배 빨라졌다"는 조건 없이는 거짓말이다. 범위가 넓어지면 유불리가 뒤집히는 인덱스인지 알 수 있게 손익분기점을 적는다.
| 항목 | 값 |
|---|---|
| 이 인덱스 경로의 손익분기 선택도 | ____ % (측정값. 추정 금지) |
| 운영에서 실제로 들어오는 조회 범위 분포 | 하루 __% · 한 달 __% · 그 이상 __% |
| 손익분기점을 넘는 조회의 비율 | ____ % |
3. 비용 ★ 비우면 반려
| 항목 | 측정값 |
|---|---|
DML 처리량 Δ (redo size) | ____ MB → ____ MB (N건 INSERT 기준) |
DML 처리량 Δ (db block changes) | ____ → ____ |
DML 처리량 Δ (session logical reads) | ____ → ____ |
| 세그먼트 예상 크기 | ____ MB |
측정 방법: INSERT 앞뒤로
V$MYSTAT을 찍는다. 워밍업 2회 뒤에 잰다. 인덱스 블록이 처음 쪼개질 때 한 번만 드는 비용이 섞이면 결과가 뒤집히기 때문이다.
3-2. 적재 비용 ★ 비우면 반려 (14화 신설)
그 테이블을 채우는 배치가 이 인덱스 때문에 얼마를 치르는가. 3번 표가 "5만 건 INSERT 한 번"의 값이라면, 이 칸은 실제 적재 경로의 값이다. 같은 인덱스라도 적재 방식에 따라 비용이 청구되는 자리가 다르다.
| 항목 | 내용 |
|---|---|
| 이 테이블을 채우는 배치 · 주기 · 건수 | (예) 주간 재적재 · 일요일 밤 · 100만 건 |
| 적재 방식 | 일반 INSERT (켠 채) / APPEND (켠 채) / 인덱스 끄고 켜기 (UNUSABLE → 적재 → REBUILD) / 파티션 교체 |
| 그 방식에서 이 인덱스 하나의 값 | 일반 INSERT면 행마다: redo ____ MB · 블록 변경 ____ / N건 · 켠 채 채우면 인덱스가 ____ % 커진다 / 끄고 켜기면 재생성 1회: ____ 초 · TEMP ____ |
| 적재 창(마감까지 여유)에 미치는 Δ | ____ 초 → ____ 초 (T3 단계 분해의 어느 줄인가) |
| 대상 테이블의 FK · 트리거 | 있으면 APPEND가 꺼진다(계획 Note 확인) → 일반 INSERT 값으로 적는다 |
| 끄고 켜기를 쓴다면, 꺼진 동안의 조회 | 이 인덱스를 쓰는 SQL이 몇 블록으로 나빠지나(Buffers N → M) · UNIQUE/PK는 끌 수 없다 |
| (파티션 테이블) LOCAL / GLOBAL | 칸 정리(DROP/TRUNCATE PARTITION) 때 GLOBAL은 UPDATE INDEXES가 필요하다 · 붙이지 않으면 UNUSABLE |
14화 실측(
T_ORD_BIG복사본 · 5만 건 · 일반 INSERT): 인덱스 0 → 1 → 2 → 3개일 때 redo 2.44 → 14.13 → 26.09 → 38.55MB · 블록 변경 1,921 → 301,704. 같은 100만 건 재적재: 일반 INSERT 켠 채 329초 · 916.6MB /APPEND+ 끄고 켜기 5.0초 · 0.6MB(재생성 3개 4.74초). 인덱스 하나의 값이 방식에 따라 수십 배 달라진다. 그래서 방식부터 적는다.
4. 중복·미사용 판정
| 항목 | 내용 |
|---|---|
| 접두 중복 인덱스 | (A)와 (A, B)가 동시에 있는가 |
DBA_INDEX_USAGE 조회 결과 | 최근 __일간 사용 횟수 |
| 이번 변경으로 지울 수 있게 되는 인덱스 |
5. 생성 방식
| 항목 | 내용 |
|---|---|
ONLINE 여부 | |
LOCAL / GLOBAL (파티션 테이블) | LOCAL Prefixed(키가 선두) · Nonprefixed(키 없는 조건이면 칸마다 한 번씩) · GLOBAL(칸 정리 시 UNUSABLE). 3-2 칸과 14화 2_파고들기 §8 참고 |
| 생성 소요 (측정) | ____ 초 |
| 생성 중 락 영향 |
6. 단계적 적용 ★ 순서를 건너뛰지 않는다
① INVISIBLE 로 생성
CREATE INDEX ... INVISIBLE;
-> 옵티마이저도, 힌트도 이 인덱스를 못 쓴다. 운영에 아무 영향이 없다
② 내 세션에서만 켜서 검증
ALTER SESSION SET OPTIMIZER_USE_INVISIBLE_INDEXES = TRUE;
-> 2번 표의 전/후를 여기서 잰다
③ [승인] ← 이 문서
④ VISIBLE 로 공개
ALTER INDEX ... VISIBLE;
⑤ 관찰기간 ____일
감시 지표: ______________ 주기: ______
⑥ 확정 또는 폐기| 단계 | 예정일 | 실제 | 결과 |
|---|---|---|---|
| ① INVISIBLE 생성 | |||
| ② 세션 검증 | |||
| ④ VISIBLE | |||
| ⑥ 확정 / 폐기 |
7. 롤백 ★ 비우면 반려
| 항목 | 내용 |
|---|---|
| 롤백 조건 (무엇이 보이면 되돌리는가) | |
| 1단계 즉시 롤백 | ALTER INDEX ... INVISIBLE; (초 단위. 계획이 원래대로 돌아간다) |
| 2단계 확정 롤백 | DROP INDEX ...; |
| 롤백 소요 예상 | |
| 되돌릴 수 없는 것 | 세그먼트가 쓴 공간은 DROP 전까지 반납되지 않는다. 인덱스 블록은 롤백해도 줄어들지 않는다 |
8. 재측정 계획
| 항목 | 내용 |
|---|---|
| 감시 지표 | Buffers · 야간 배치 소요 · DBA_INDEX_USAGE |
| 주기 | |
| CF 재측정 주기 ★ | CF는 적재가 계속되면 나빠진다. 분기에 1회 이상 다시 잰다 |
금지어
"빨라졌다", "느리다", "무겁다", "많이 개선됨"은 쓰지 않는다. 모두 N → M 수치로 바꿔 쓴다. 그리고 그 수치 옆에 조회 범위(행수·선택도)를 같이 적는다. 범위 없는 배수는 숫자가 아니라 인상일 뿐이다.
자매 문서
- T1 단건 SQL 튜닝 리포트: 02화 제정
- T3 배치 SLA 리포트: 14화 제정(3-2의 '적재 창 Δ'를 단계 분해로 받는다)
- 힌트 유효기간 대장: 06화 제정(레거시 힌트 전수 목록 / 붙은 시점의 데이터 규모 / 현재 규모 / 폐기·유지 판정)
개정 이력
| 판 | 화 | 무엇이 바뀌었나 | 왜 |
|---|---|---|---|
| v1 | 04화 | 제정. 1~8번 칸. T2-001(버거원 커버링) · T2-002(IX_ORD_BIG_DT 폐기, 승인 대기) | 측정 수치 없이 "RANGE SCAN으로 변경 완료"라고만 쓴 보고서 |
| v2 | 14화 | 「3-2 적재 비용」 칸 신설 · 3번의 「【14화】 야간 배치 적재 소요 Δ」 한 줄을 그 칸으로 옮겨 넓힘 · 5번 LOCAL/GLOBAL 칸 채움 | 14화 야간 체인 초과의 몸통은 인덱스 3개를 켠 채 한 행씩 넣는 재적재(연습 DB 329초 · redo 916.6MB)였다. 02·09화에 인덱스를 승인할 때는 적재 비용 칸이 '야간 배치 소요 Δ' 한 줄뿐이라 비어 있었다. 게다가 재 보니 같은 인덱스라도 적재 방식에 따라 값이 수십 배 달랐다(일반 INSERT 켠 채 vs 끄고 켜기 5.0초). 한 줄로는 값이 정해지지 않는다. 그래서 '방식'을 먼저 적고 그 방식에서의 값을 적게 했다. 첫 적용 = T2-002 마무리(14화 3_실습과_기록.md STEP 10) |
| v2 | 18화 | (양식 그대로) T2-002 갱신: INVISIBLE로 한 걸음 · 계획 변화 0 · AWR 0 SQL / 1~53 → INVISIBLE 단계 승인 · DROP은 운영 소스 전수 조사 뒤(18화 3_실습 STEP 11-6) · 사내 튜닝 표준 제12조 · 체크리스트 C1이 PR마다 이 양식을 요구 | 폐기를 '안 쓰인다'는 믿음이 아니라 세 가지 증거로 판단 |