티스토리 뷰

Database/Oracle

실행계획

데브포유 2026. 7. 21. 16:42
반응형

  헷갈릴 때 체크리스트

  1. 노드 앞에 붙은 이름이 HASH JOIN 이면 → 첫 자식이 Build, 다 읽고 시작
  2. NESTED LOOPS 면 → 첫 자식(드라이빙)부터 한 행씩, 각 행마다 둘째 자식
  3. VIEW 표시 있으면 → 그 서브트리는 하나의 결과셋으로 먼저 완성됨 (인라인뷰/서브쿼리 블록)
  4. PARTITION RANGE ... 는 실행 주체가 아니라 파티션 프루닝 껍데기 — 안쪽 테이블 액세스랑 세트로 보기

 

오라클 실행계획 해석 정리

1. 읽는 순서 (핵심 3원칙)

① 형제(sibling) 중에는 위(첫 번째 자식) 먼저
② 자식이 있으면 자식 서브트리를 끝까지 파고든 뒤 형제로 이동
③ HASH JOIN 만나면: 첫 자식(Build) 완전 종료 → 둘째 자식(Probe) 시작
한 줄 요약: "위에서 아래로, 안쪽부터 바깥쪽으로"

2. 조인 방식 3가지

조인 동작 방식 첫 자식 = 언제 유리?
NESTED LOOPS 한 행씩 스트림. 바깥 행 → 안쪽 인덱스 콕 드라이빙(outer) 소량 처리, 안쪽 인덱스 좋을 때
HASH JOIN Build 다 뽑아 해시 → Probe 흘려보냄 Build(작은 쪽) 대량 처리, 인덱스 없어도 OK
MERGE JOIN 양쪽 정렬 후 지퍼처럼 병합 정렬된 첫 소스 이미 정렬돼 있거나 대량 범위

3. 테이블 액세스 방법

Operation 의미
TABLE ACCESS FULL 풀 스캔 (전체 블록 읽음)
TABLE ACCESS BY INDEX ROWID 인덱스로 ROWID 얻어 테이블 접근
TABLE ACCESS BY LOCAL INDEX ROWID 위와 동일, 파티션 로컬 인덱스
INDEX UNIQUE SCAN PK/UK 로 한 건
INDEX RANGE SCAN 범위 조회 (=, BETWEEN, LIKE 'A%')
INDEX FULL SCAN 인덱스 전체를 정렬 순
INDEX FAST FULL SCAN 멀티블록 IO로 인덱스 전체
INDEX SKIP SCAN 선두 컬럼 스킵 (선두 카디널리티 낮을 때)

4. 그 외 자주 나오는 오퍼레이션

Operation 의미
VIEW 인라인뷰/서브쿼리 블록 — 하나의 결과셋으로 먼저 완성됨
SORT AGGREGATE 단순 집계 (COUNT(*), SUM 등)
SORT GROUP BY / HASH GROUP BY GROUP BY (정렬형 / 해시형)
SORT ORDER BY ORDER BY 정렬
SORT UNIQUE 중복 제거 정렬
UNION-ALL / CONCATENATION 결과 이어붙이기
FILTER 서브쿼리로 필터링 (반복 실행 주의)
COUNT STOPKEY ROWNUM <= N 최적화

5. 파티션 오퍼레이션

Operation 의미
PARTITION RANGE SINGLE 파티션 1개 접근 (완벽 프루닝)
PARTITION RANGE ITERATOR 파티션 여러 개 순회
PARTITION RANGE ALL 모든 파티션 접근 (프루닝 실패)
Pstart / Pstop 접근하는 파티션 번호 (KEY = 실행 중 결정)
⚠ RANGE ALL 이 보이면 파티션 프루닝 실패 → 파티션 키 조건 확인!

6. 컬럼별 확인 포인트

컬럼 봐야 할 것
Rows 옵티마이저의 추정 건수 (실제와 다를 수 있음)
Bytes 예상 데이터 크기
Cost 옵티마이저의 상대적 비용 (절대값 아님)
TempSpc 임시 테이블스페이스 사용 예정 (정렬/해시 스필)
Pstart/Pstop 파티션 접근 범위
Rows 추정이 실제와 크게 다르면 통계 문제 의심 (DBMS_STATS)

7. 실전 해석 흐름 (5단계)

1. 트리 구조로 먼저 그리기 (들여쓰기 = 부모/자식)
2. 리프(leaf)부터 어떤 테이블에 어떻게 접근하는지 확인
3. 각 조인의 종류 확인 → 드라이빙/Build 파악
4. VIEW/GROUP BY/SORT 위치 확인 → 중간 집계·정렬 지점
5. 파티션 프루닝 여부 확인 (Pstart/Pstop)

8. 튜닝 관점 체크리스트

  • ✅ TABLE ACCESS FULL — 대용량 테이블이면 인덱스 or 파티셔닝 검토
  • ✅ NESTED LOOPS 인데 안쪽 FULL SCAN — 인덱스 없음, 반복 풀스캔 재앙
  • ✅ HASH JOIN + TempSpc 사용 — PGA 부족, 스필 발생
  • ✅ PARTITION RANGE ALL — 파티션 프루닝 실패
  • ✅ INDEX FULL SCAN + FILTER — 인덱스 컬럼 순서/조건 재검토
  • ✅ Rows 추정 vs 실제 10배 이상 차이 — 통계 갱신 or 힌트
  • ✅ * 표시된 라인 (predicate) — Predicate 섹션에서 조건 확인
  • ✅ 동일 서브쿼리 반복 실행 (FILTER) — 스칼라 서브쿼리/조인 변환 검토

9. 빠른 판독 치트키

"뷰가 있다"           → 그 서브트리는 하나의 덩어리로 먼저 완성
"HJ가 있다"           → 첫 자식은 Build, 미리 다 읽음
"NL이 있다"           → 첫 자식이 드라이빙, 한 행씩 반복
"파티션 있다"          → Pstart/Pstop이 KEY면 실행 중 결정
"* 표시 있다"          → 아래 Predicate Information 꼭 보기
"Rows 뻥튀기"          → 통계 or 조건절 문제

이 정도만 머리에 있으면 웬만한 플랜은 트리 그리고 → 조인 방식 표시 → 드라이빙 화살표 그리기 3분이면 흐름 파악됩니다.
실무에선 Predicate Information(술어)과 Note(다이나믹 샘플링/카디널리티 피드백 등)도 같이 봐야 정확한 튜닝 포인트가 잡힙니다.

 

반응형