🎯 학습 목표
- 실행계획을 뽑는 3가지 방법을 사용한다.
- 실행계획을 “위→아래, 안쪽→바깥쪽” 순서로 읽는다.
- Rows·Cost·실제 일량(logical reads)을 해석한다.
📖 실행계획이란?
실행계획(Execution Plan)은 옵티마이저가 “이 SQL을 이렇게 실행하겠다”고 정한 작업 순서표입니다. 어떤 테이블을 먼저 읽고, 인덱스를 탈지 전체 스캔할지, 조인을 어떤 방식으로 할지가 모두 담겨 있습니다. 튜닝은 실행계획을 보는 것에서 시작합니다. 계획을 보지 않고 SQL을 고치는 것은 지도 없이 운전하는 것과 같습니다.
💻 방법 1) EXPLAIN PLAN — 실행하지 않고 계획만 보기
EXPLAIN PLAN FOR
SELECT * FROM emp WHERE deptno = 10;
-- 보기 좋게 출력
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
SQL을 실제로 돌리지 않고 예상 계획만 봅니다. 빠르지만 “예상”이라 실제와 다를 수 있습니다.
💻 방법 2) AUTOTRACE — 실행하면서 계획 + 통계 보기 (SQL*Plus)
SET AUTOTRACE ON
SELECT * FROM emp WHERE deptno = 10;
-- 결과 + 실행계획 + Statistics(consistent gets, physical reads 등)가 함께 출력됨
여기서 consistent gets(= logical reads, 읽은 블록 수)가 튜닝의 핵심 숫자입니다. 결과는 10건인데 consistent gets가 수만이라면 “일을 너무 많이 했다”는 신호입니다.
💻 방법 3) 실제 실행된 계획 보기 (가장 정확)
-- SQL에 힌트로 통계 수집을 켜고 실행
SELECT /*+ GATHER_PLAN_STATISTICS */ * FROM emp WHERE deptno = 10;
-- 방금 실행한 SQL의 '실제' 계획 + 예상 vs 실제 행수 비교
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
E-Rows(예상 행수)와 A-Rows(실제 행수)가 크게 어긋나면 통계가 부정확하다는 뜻이고, 이는 옵티마이저가 잘못된 계획을 고르는 흔한 원인입니다(6강).
📖 실행계획 읽는 법 — 들여쓰기가 핵심
----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost |
----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 2 |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP | 10 | 2 |
| 2 | INDEX RANGE SCAN | EMP_DEPT_IX | 10 | 1 |
----------------------------------------------------------------
읽는 순서: 가장 안쪽(들여쓰기 깊은) + 위에서부터
① INDEX RANGE SCAN (Id 2) → 인덱스에서 deptno=10인 ROWID들을 찾고
② TABLE ACCESS BY INDEX ROWID (Id 1) → 그 ROWID로 테이블 행을 읽는다
③ SELECT STATEMENT (Id 0) → 결과 반환
규칙: 들여쓰기가 가장 깊은 줄(가장 안쪽)부터, 같은 깊이면 위에서 아래로 읽습니다. 각 줄의 결과가 바로 바깥(부모) 줄의 입력이 됩니다.
📖 꼭 알아둘 핵심 Operation
TABLE ACCESS FULL : 테이블 전체 스캔 (작은 테이블/넓은 범위엔 OK, 좁은 검색엔 경고 신호)
INDEX RANGE SCAN : 인덱스로 범위 검색 (보통 좋은 신호)
INDEX UNIQUE SCAN : 유니크 인덱스로 1건 검색
TABLE ACCESS BY INDEX ROWID: 인덱스로 찾은 ROWID로 테이블 접근
NESTED LOOPS / HASH JOIN : 조인 방식 (5강)
⚠️ 주의사항
Cost는 옵티마이저의 상대적 예상치일 뿐, 실제 시간이 아닙니다. Cost가 낮다고 항상 빠른 것은 아닙니다. 최종 판단은 실제 logical reads와 실행 시간으로 합니다.- EXPLAIN PLAN의 “예상”과 실제 실행 계획이 다를 수 있습니다. 정확히 보려면 방법 3(DISPLAY_CURSOR)을 쓰세요.
💡 팁
- 실행계획에서 가장 먼저 찾을 것: 좁은 검색인데
TABLE ACCESS FULL이 보이는가? → 인덱스 미사용 의심(3·4강). - 그 다음: 예상 행수(E-Rows)와 실제 행수(A-Rows)가 크게 다른가? → 통계 문제 의심(6강).