PostgreSQL · 2026-03-14

PostGIS 인덱스와 공간 쿼리 튜닝

PostGIS에서 공간 인덱스를 올바르게 설정하고 GIST/SPGIST 선택, 쿼리 작성법, EXPLAIN 분석, 유지보수 절차를 사례와 명령어로 정리한 설명

작성일 : 2026-03-14 ㆍ 작성자 : 관리자
post
목차

개요

공간 데이터를 다루면 인덱스와 쿼리 패턴이 성능을 좌우한다. PostGIS는 공간 연산을 위해 특화된 인덱스와 함수들을 제공한다. 이 글에서는 인덱스 종류, 설정 방법, 쿼리 작성 방식, 그리고 성능 분석과 유지보수를 단계별로 설명한다. 처음 접하는 사용자가 이해하기 쉽게 실전 예제 중심으로 정리한다.

왜 공간 인덱스가 필요한가

일반적인 B-Tree 인덱스는 좌표나 기하학 연산을 빠르게 처리하지 못한다. 공간 인덱스는 영역 기반의 검색을 빠르게 수행한다. 따라서 공간 조인, 거리 검색, 다각형 교차 검사 등에서 비용을 크게 줄여준다.

인덱스 종류와 선택 기준

GIST 인덱스

가장 널리 쓰이는 인덱스다. 범위 질의와 교차 검사에 강하다. 복합 인덱스로 다른 컬럼과 조합 가능하다. 대부분의 경우 기본 선택지다.

SPGIST 인덱스

고르게 분포된 포인트 데이터나 매우 큰 데이터셋에서 유리하다. 일부 분포에서는 GIST보다 성능이 좋을 수 있다. 삽입 비용과 구조적 특성이 다르므로 테스트가 필요하다.

기타 고려사항

  • geometry vs geography: 거리 계산과 정확도 요구에 따라 선택.
  • 데이터 분포: 포인트 밀집, 선형 구조, 넓은 다각형 등으로 인덱스 성능이 달라짐.
  • 복합 인덱스: 공간 인덱스와 속성 인덱스를 함께 사용하면 필터 단계에서 유리.

인덱스 생성 예시

기본적인 GIST 인덱스 생성 예제.

CREATE INDEX idx_places_geom_gist ON places USING GIST(geom);

공간 컬럼과 다른 속성을 함께 인덱스에 포함할 때.

CREATE INDEX idx_places_geom_status ON places USING GIST(geom, status);

SPGIST 예제 (포인트에 적합).

CREATE INDEX idx_points_geom_spgist ON points USING SPGIST(geom);

효율적인 쿼리 작성법

인덱스를 활용하려면 검색 패턴이 인덱스 연산자와 맞아야 한다. 대표적인 방법을 정리한다.

박스 필터로 범위 축소

복잡한 지오메트리 연산 전에 단순한 박스(BBOX)로 후보를 줄이면 성능이 좋아진다.

SELECT id FROM places
WHERE geom && ST_MakeEnvelope(xmin, ymin, xmax, ymax, 4326)
AND ST_Intersects(geom, ST_GeomFromText('POLYGON(...)', 4326));

거리 검색

거리 기반 검색은 ST_DWithin을 우선 사용한다. ST_DWithin은 인덱스를 잘 이용한다.

SELECT id, name FROM places
WHERE ST_DWithin(geom::geography, ST_SetSRID(ST_MakePoint(lon, lat), 4326)::geography, 5000);

공간 조인

공간 조인 시에도 먼저 박스 필터로 후보를 줄이고 그 다음 정확한 공간 연산을 적용한다.

SELECT a.id, b.id FROM a JOIN b
ON a.geom && b.geom
AND ST_Intersects(a.geom, b.geom);

성능 분석: EXPLAIN과 EXPLAIN ANALYZE

쿼리 플랜을 확인하면 인덱스 사용 여부와 병목 지점을 파악할 수 있다. EXPLAIN ANALYZE로 실제 실행 비용을 확인한다.

EXPLAIN ANALYZE
SELECT id FROM places
WHERE geom && ST_MakeEnvelope(...)
AND ST_Intersects(geom, ST_GeomFromText('POLYGON(...)', 4326));

출력에서 Index Scan 또는 Bitmap Index Scan이 보이면 인덱스가 활용된 것이다. 그렇지 않다면 쿼리 형태나 통계가 문제일 수 있다.

통계와 유지보수

ANALYZE로 통계를 최신 상태로 유지해야 옵티마이저가 올바른 계획을 선택한다. 또한 VACUUM과 REINDEX를 적절히 수행한다.

  • ANALYZE table_name;
  • VACUUM (VERBOSE, ANALYZE) table_name;
  • REINDEX INDEX index_name;

데이터 삽입이 많을 경우 인덱스 재구성 비용을 고려해 배치로 삽입 후 재색인하는 것이 유리하다.

추가 최적화 기법

  • 클러스터링: 큰 테이블은 CLUSTER로 물리적 정렬하여 범위 쿼리 성능 개선.
  • 파티셔닝: 지역 단위 또는 시간 단위로 파티셔닝하면 스캔 범위를 줄일 수 있음.
  • 병렬 쿼리: 공유 버퍼와 work_mem 조정으로 병렬 처리를 활용.
  • 함수 인덱스: 자주 쓰는 변형(예: ST_Transform)을 인덱스로 만들어 필터링 단계에서 활용.

마무리

요약하면 적절한 인덱스 선택과 쿼리 작성, 통계 유지가 핵심이다. 먼저 데이터 분포와 쿼리 패턴을 파악하고 GIST 또는 SPGIST 중 적합한 것을 선택한다. 쿼리 작성 시 박스 필터와 ST_DWithin 같은 인덱스 친화적 함수를 우선 사용한다. 마지막으로 EXPLAIN ANALYZE로 결과를 검증하고 정기적인 ANALYZE, VACUUM을 수행한다. 이 과정을 반복하면 실무에서 안정적인 공간 쿼리 성능을 확보할 수 있다.

postgis 인덱스 설정 공간 쿼리 최적화 postgis postgis spatial index postgres postgis gis 인덱스 postgresql 튜닝 ST_DWithin GIST SPGIST