핵심 요약
인덱스를 만들었는데 EXPLAIN에 Seq Scan이 나온다면, ① 컬럼을 함수로 가공하거나 형변환해서(인덱스 무력화), ② 결과가 테이블 대부분이라 옵티마이저가 풀스캔이 더 싸다고 판단했거나, ③ 통계가 낡았기 때문이다. 대부분 쿼리 작성 방식의 문제다.
1. 원인별 처방
| 원인 | 해결 |
|---|---|
| WHERE lower(email)=... | 표현식 인덱스 또는 저장 시 정규화 |
| 형 불일치(text vs int) | 타입 맞추기 |
| LIKE '%키워드%' | trigram(pg_trgm) 인덱스 |
| 통계 낡음 | ANALYZE 실행 |
2. 확인
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM users WHERE email = $1;
-- Seq Scan 이면 인덱스 미사용, Index Scan 이면 정상
3. 함정
- 소량 테이블은 옵티마이저가 일부러 Seq Scan — 정상이다
- 선택도가 낮으면(거의 다 매칭) 인덱스가 오히려 느려 안 쓴다
- OR 조건·앞쪽 와일드카드 LIKE는 일반 B-tree로 못 탄다
자주 묻는 질문
인덱스가 있는데 왜 Seq Scan을 하나요?
옵티마이저가 비용을 계산해 풀스캔이 더 싸다고 보면 그렇게 합니다. 결과가 테이블의 큰 비율이거나 통계가 낡았을 때 흔합니다. ANALYZE 후 다시 확인하세요.
LIKE '%word%'는 왜 인덱스를 못 타나요?
앞에 와일드카드가 있으면 B-tree 정렬 순서를 활용할 수 없습니다. pg_trgm 확장의 GIN/GiST 인덱스를 쓰면 부분 일치도 가속됩니다.

댓글 0