콘텐츠로 이동

인덱스가 있는데 왜 데이터베이스에서 전체 테이블 스캔을 하나요

📝 [강의 노트] DB 공학 기초: 인덱스와 쿼리 플래너의 비밀

1. 오늘의 질문 (Q&A)

  • 상황: ID 컬럼에 인덱스를 생성했는데, WHERE id = 2 쿼리를 실행하니 인덱스 스캔이 아닌 순차 스캔(Sequential Scan)이 발생함.
  • 원인: 왜 데이터베이스는 내 말을 듣지 않고 비효율적(?)으로 보이는 순차 스캔을 선택했을까?

2. 핵심 원리: 플래너의 '비용 계산'

데이터베이스 플래너는 쿼리를 실행하기 전, 어떤 방식이 가장 저렴(저비용 I/O)할지 계산한다.

  • 인덱스 스캔(Index Scan):
  • 복잡한 B-Tree 구조를 타고 내려가야 함 (루트 → 중간 → 잎 노드).
  • 인덱스 파일을 열고 탐색한 뒤, 다시 실제 데이터 파일(Heap)로 이동하는 추가 작업 발생.

  • 순차 스캔(Sequential Scan):

  • 데이터 파일을 처음부터 끝까지 읽음.

💡 Case A: 테이블이 너무 작은 경우 (행 7개)

  • 결론: 순차 스캔 승리!
  • 데이터가 단 7행뿐이라면 전체 용량이 약 8KB(1페이지) 내외다.
  • 플래너 입장: "겨우 한 페이지 읽으면 끝나는데, 굳이 복잡한 B-Tree 인덱스까지 뒤져서 일을 두 번 할 필요가 있나?"
  • 즉, 데이터가 적을 때는 인덱스를 안 쓰는 게 더 빠르다.

3. 실무 주의사항: 대량 데이터 삽입 시의 함정

작은 테이블(행 7개)에 갑자기 300만 건의 데이터를 밀어 넣었을 때 발생하는 문제.

  • 현상: 쿼리가 갑자기 미친 듯이 느려짐.
  • 이유: 플래너가 가진 통계 정보(Statistics)가 업데이트되지 않았기 때문.
  • 플래너의 착각: "내 장부에는 이 테이블이 아직 행 7개짜리 꼬마라고 적혀있어. 그러니 인덱스 대신 순차 스캔을 할게!"
  • 실제 결과: 300만 건을 인덱스 없이 하나하나 다 읽느라 시스템 과부하 발생.

4. 해결책: 통계 정보 최신화

데이터에 큰 변화(Bulk Insert/Update)가 생기면 반드시 데이터베이스에게 알려줘야 한다.

  • PostgreSQL: VACUUM ANALYZE (특히 ANALYZE가 통계를 갱신함)
  • Oracle: Gather Schema Statistics
  • SQL Server: Update Statistics

📌 요약 한 줄 평: 인덱스는 만능 도구가 아니다. 데이터의 양과 최신 통계 정보가 뒷받침되어야 플래너가 똑똑한 결정을 내릴 수 있다.