본문 바로가기
IT

실행계획과 인덱스

by urosie 2025. 12. 16.
반응형

1. 실행계획은 어떻게 읽어야 하나

실행계획은 위에서 아래로 읽지 않는다. 안쪽(오른쪽, 가장 아래)부터 바깥쪽으로 실행된다.

즉, 성능은 항상 첫 테이블 접근 방식에서 대부분 결정된다.


2. 실행계획에서 반드시 봐야 하는 핵심 지표

Rows (Cardinality)

  • 옵티마이저가 "이 단계에서 몇 건이 나올 것"이라 예상한 값
  • 실행계획의 모든 판단 기준

Rows가 틀리면 조인 방식, 인덱스 선택, 실행 순서 전부 틀어진다.

E-Rows vs A-Rows

  • E-Rows: 예상 행 수
  • A-Rows: 실제 실행 행 수

5~10배 이상 차이면 무조건 튜닝 대상


3. 테이블 접근 방식 한 줄 요약

  • TABLE ACCESS FULL
    → 테이블 전체를 읽음. 대량 데이터면 위험 신호
  • TABLE ACCESS BY ROWID
    → 인덱스로 위치를 찾은 뒤 테이블 접근

4. 인덱스 스캔 방식 정리 (한 줄 요약)

  • INDEX UNIQUE SCAN
    → PK/UK 조회. 가장 이상적인 형태
  • INDEX RANGE SCAN
    → 조건 범위에 해당하는 인덱스 구간만 탐색
  • INDEX FULL SCAN
    → 인덱스를 처음부터 끝까지 읽음 (대체로 좋지 않음)
  • INDEX FAST FULL SCAN
    → 인덱스를 정렬 무시하고 통째로 읽음 (집계용)

5. WHERE 조건과 인덱스의 관계

인덱스는 WHERE 조건으로 얼마나 줄일 수 있느냐가 전부다.

좋은 조건

WHERE user_id = :id

→ 선택도 높음, 인덱스 효과 큼

나쁜 조건

WHERE status = 'Y'

→ 값 종류 적음, 단독 인덱스 의미 거의 없음


6. JOIN 조건에서 인덱스는 언제 필요한가

JOIN 인덱스의 목적은 하나다.

NESTED LOOP를 가능하게 만드는 것

  • 자식 테이블(FK 쪽)에 인덱스 필수
  • 부모 테이블은 PK로 충분한 경우가 대부분

7. 복합 인덱스와 선두 컬럼의 의미

INDEX (A, B, C)

이 인덱스는 내부적으로 A → B → C 순으로 정렬된다.

제대로 타는 경우

WHERE A = 1 AND B = 10

선두 컬럼을 못 쓰는 경우

WHERE B = 10

→ A 조건이 없으면 인덱스는 사실상 무력화된다.


8. 범위 조건이 끼면 그 뒤 컬럼은 사용 불가

WHERE A = 1
AND B BETWEEN 10 AND 20
AND C = 5
  • A: 사용
  • B: 사용
  • C: 인덱스 탐색 불가

= 조건 → 범위 조건 → 이후 컬럼은 장식


9. 인덱스를 만들어도 성능이 안 나오는 대표적인 이유

  1. 결과 행이 너무 많음 (선택도 낮음)
  2. 함수 / 가공으로 인덱스 무력화
  3. 복합 인덱스 선두 컬럼 누락
  4. 컬럼 타입 불일치
  5. 통계 정보 오류
  6. LIKE '%값' 패턴
  7. 조인 순서 자체가 잘못됨

10. 인덱스를 많이 만들면 왜 느려질까

  • INSERT / UPDATE / DELETE 시 인덱스 전부 갱신
  • 인덱스 블록 락 경합 증가
  • 옵티마이저 선택지 과다 → 오판 확률 증가
  • 버퍼 캐시 낭비

인덱스는 읽기 성능 도구이자 쓰기 성능 부채다.


11. 실행계획 문제는 결국 WAS 장애로 이어진다

잘못된 실행계획 →

  • 쿼리 지연
  • 트랜잭션 장기 유지
  • 커넥션 점유 증가
  • HikariCP active 상승
  • Connection timeout 발생

실행계획 튜닝은 DB 문제가 아니라 서비스 안정성 문제다.


12. 정리

  • 실행계획은 Cost가 아니라 Rows를 본다
  • 인덱스는 선두 컬럼부터 연속으로 써야 의미 있다
  • 인덱스는 많을수록 위험하다

"실행계획을 못 보면 장애 원인을 절반도 못 본다."

반응형

댓글