SQLP · 실행계획과 인덱스
SQLP 실행계획 읽기: 인덱스가 있어도 Seq Scan이 나오는 이유
SQLP 문제에서 인덱스가 보인다고 실행계획에 반드시 Index Scan이 나오는 것은 아닙니다. PostgreSQL은 후보 계획의 예상 비용을 비교합니다. 아래 원본 사례에서 먼저 읽을 것은 인덱스의 존재 여부보다 검색 조건과 실제로 읽어야 할 행의 범위입니다.
실행계획을 읽는 세 단계
- 접근 방식:
Seq Scan,Index Scan,Bitmap Index Scan중 어떤 노드로 행을 찾는지 봅니다. - 조건 위치:
Index Cond가 인덱스 범위를 좁히는 조건인지,Filter가 읽은 행을 다시 거르는 조건인지 구분합니다. - 예상과 실제: 기본
EXPLAIN의rows와cost는 계획 시 추정치입니다. 실제 행 수를 보려면 안전한 읽기 쿼리에서EXPLAIN ANALYZE를 사용합니다. 이 명령은 쿼리를 실제 실행하므로 쓰기 쿼리에는 주의해야 합니다.
실행계획은 데이터 양·분포·통계와 쿼리에 따라 달라집니다. 아래 SQL은 개념을 설명하는 예시이며, 특정 서버에서 같은 계획이 출력된다고 주장하지 않습니다.
인덱스가 있어도 먼저 확인할 세 상황
1. 모든 주문을 읽는다면
CREATE INDEX orders_customer_idx ON orders (customer_id);
EXPLAIN SELECT * FROM orders;customer_id 인덱스가 있어도 WHERE 조건이 없는 쿼리는 모든 주문을 읽습니다. PostgreSQL 공식 문서의 전체 테이블 조회 예제도 Seq Scan을 선택합니다. 이때 인덱스가 사용되지 않았다는 사실만으로 결함이라 단정하지 마세요. 먼저 쿼리가 정말 전체 행을 필요로 하는지 확인합니다.
2. 인덱스 열을 함수로 바꿔 비교한다면
CREATE INDEX customers_email_idx ON customers (email);
EXPLAIN SELECT * FROM customers
WHERE lower(email) = 'learner@example.com';email에 만든 일반 인덱스와 lower(email)의 결과는 같은 검색 키가 아닙니다. PostgreSQL은 이 검색용으로 lower(email) 표현식 인덱스를 만들 수 있다고 설명합니다. 인덱스를 추가하기 전에 실제 쿼리 빈도와 쓰기 비용을 함께 확인하세요.
3. 다중 열 인덱스의 앞 열이 빠졌다면
CREATE INDEX orders_region_date_idx
ON orders (region, created_at);
EXPLAIN SELECT * FROM orders
WHERE created_at >= DATE '2026-11-01';(region, created_at) 인덱스는 앞쪽 열 region에 조건이 있을 때 검색 범위를 더 효율적으로 줄일 수 있습니다. created_at만 조건에 있어도 인덱스 사용이 불가능한 것은 아닙니다. 다만 읽어야 할 인덱스 범위가 넓어질 수 있으므로, WHERE region = 'CA' AND created_at >= ...처럼 앞 열까지 제한하는 경우와 계획을 비교합니다.
원본 확인 문제 · 실제 기출 문항 아님
어느 판단부터 해야 할까요?
email 열에 일반 B-tree 인덱스가 있습니다. 쿼리는 WHERE lower(email) = 'a@example.com'이고 실행계획에는 Seq Scan이 보입니다. 다음 행동으로 가장 알맞은 것은 무엇일까요?
- 인덱스가 고장 났다고 보고 즉시 삭제한다.
- 검색식이 인덱스 키와 일치하는지 확인하고, 실제 데이터에서 계획과 비용을 비교한다.
- 모든 쿼리의 순차 스캔을 강제로 금지한다.
정답과 선택지별 이유 보기
정답은 2번입니다. 일반 email 인덱스와 lower(email) 검색식이 다르므로 먼저 조건과 인덱스 정의를 대조합니다. 필요하면 표현식 인덱스를 검토하되 비용·유지 부담을 같이 봅니다. 1번은 인덱스의 고장을 입증하지 못하며, 3번은 다른 쿼리에 유리한 순차 스캔까지 막을 수 있습니다.
공식 근거와 적용 범위
PostgreSQL 17: Using EXPLAIN은 계획 노드와 예상 비용을, Indexes on Expressions는 lower() 검색을, Multicolumn Indexes는 앞 열 조건의 효율을 설명합니다.
DataQ SQLP 종목 안내에서 자격 종목을 확인하세요. 이 글은 PostgreSQL로 원리를 연습하는 자체 학습 자료이며 SQLP의 공식 기출문제나 모든 DBMS의 동일한 실행계획을 재현한 자료가 아닙니다.