ClickHouse에서 greatCircleDistance: 전체 테이블 스캔 방지

발행: (2026년 4월 21일 AM 01:18 GMT+9)
4 분 소요
원문: Dev.to

Source: Dev.to

Cover image for greatCircleDistance in ClickHouse: Avoiding Full Table Scans

문제점

위치 데이터를 다룰 때 흔히 묻는 질문은 다음과 같습니다:

데이터베이스에 저장된 두 좌표 사이의 거리를 어떻게 계산할까?

ClickHouse를 사용한다면, 데이터베이스 외부에서 처리할 필요가 없습니다—내장 함수가 제공됩니다.

올바른 도구: greatCircleDistance

greatCircleDistance(lat1, lon1, lat2, lon2)

지구상의 두 지점 사이의 최단 거리를 미터 단위로 반환합니다.

예시

SELECT greatCircleDistance(13.0827, 80.2707, 12.9716, 77.5946) AS distance_meters;

위 쿼리는 첸나이와 방갈로르 사이의 거리를 반환합니다.

간단해 보이지만… 함정이 있습니다

다음과 같은 순진한 쿼리:

SELECT city
FROM locations
WHERE greatCircleDistance(lat, lon, 13.0827, 80.2707) < 5000;

은 괜찮아 보이지만, 대용량 테이블에서는 전체 테이블 스캔을 유발할 수 있습니다.

왜 이런 일이 발생할까

ClickHouse 인덱스는 **희소(sparse)**하며 **범위 프루닝(range pruning)**을 위해 설계되었습니다. 다음과 같은 조건에서는 잘 동작합니다:

WHERE lat BETWEEN x AND y

하지만 다음과 같은 경우에는 동작하지 않습니다:

WHERE greatCircleDistance(lat, lon, x, y) < 5000

함수가 컬럼 값에 직접 적용되기 때문에 ClickHouse는 인덱스를 활용해 데이터를 효율적으로 건너뛸 수 없습니다.

더 나은 접근법 (실제로 해야 할 일)

먼저 바운딩 박스 필터로 데이터셋을 축소한 뒤, 정확한 거리 계산을 적용합니다.

바운딩 박스 필터

SELECT city
FROM locations
WHERE lat BETWEEN (13.0827 - 0.05) AND (13.0827 + 0.05)
  AND lon BETWEEN (80.2707 - 0.05) AND (80.2707 + 0.05)
  AND greatCircleDistance(lat, lon, 13.0827, 80.2707) < 5000;

바운딩 박스는 정확한 greatCircleDistance 검사를 수행하기 전에 검색 범위를 좁히는 근사값입니다.

왜 이렇게 하면 되는가

  • lat BETWEEN … → 인덱스를 사용
  • lon BETWEEN … → 행을 추가로 감소
  • greatCircleDistance → 필터링된 부분집합에만 적용

따라서 전체 테이블을 스캔하지 않게 됩니다.

실제 활용 사례

  • 배달 반경 필터링
  • 인근 사용자 찾기
  • 지리 기반 분석
  • 라이드셰어링 시스템

한 가지 중요한 주의점

  • 좌표는 도(degrees) 단위여야 합니다(라디안이 아님).
  • 순서는 항상 (lat, lon)입니다. 순서를 바꾸면 잘못된 결과가 나옵니다.

마무리 생각

greatCircleDistance는 강력하지만 무분별하게 사용하면 성능에 악영향을 줄 수 있습니다. ClickHouse에서는 쿼리 설계가 함수 호출보다 더 중요할 때가 많습니다. 인덱스 친화적인 사전 필터 이후에 greatCircleDistance언제, 어떻게 적용할지 아는 것이 효율적이고 확장 가능한 지리 쿼리를 보장합니다.

0 조회
Back to Blog

관련 글

더 보기 »

SQL에서 서브쿼리와 CTE

SQL을 사용할 때 결국 단일 query만으로는 충분하지 않은 상황에 직면하게 됩니다. 문제를 여러 부분으로 나누고, intermediate 결과를 계산해야 합니다.