지리 / 공간 쿼리
Oracle
-- Oracle Spatial: SDO_GEOMETRY column and spatial index
CREATE INDEX location_sidx ON shop(location)
INDEXTYPE IS MDSYS.SPATIAL_INDEX;
-- Shops within 5 km:
SELECT name FROM shop
WHERE SDO_WITHIN_DISTANCE(location,
SDO_GEOMETRY(2001, 4326,
SDO_POINT_TYPE(32.85, 39.92, NULL), NULL, NULL),
'distance=5 unit=KM') = 'TRUE';Oracle Spatial은 지리 데이터를 SDO_GEOMETRY 타입에 저장하며, USER_SDO_GEOM_METADATA 항목과 공간 인덱스가 필요하다. SDO_WITHIN_DISTANCE, SDO_RELATE, SDO_NN 같은 연산자가 거리/교차/최근접 이웃 쿼리를 처리한다. SRID 4326은 WGS84(위도/경도) 체계다.
PostgreSQL
-- PostGIS extension:
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE INDEX location_gix ON shop USING GIST (location);
-- Shops within 5 km (geography, meters):
SELECT name FROM shop
WHERE ST_DWithin(location,
ST_SetSRID(ST_MakePoint(32.85, 39.92), 4326)::geography,
5000);PostGIS는 PostgreSQL을 완전한 기능의 공간 데이터베이스로 만든다. geometry(평면)와 geography(구면) 타입, 그리고 ST_Distance/ST_DWithin/ST_Intersects/ST_Contains 같은 수백 개의 ST_ 함수를 제공한다. GiST/SP-GiST 인덱스가 공간 쿼리 속도를 높인다.
MySQL
-- Spatial column (with SRID) and SPATIAL index:
ALTER TABLE shop MODIFY location POINT NOT NULL SRID 4326;
ALTER TABLE shop ADD SPATIAL INDEX (location);
-- Compute distance (meters, geography):
SELECT name,
ST_Distance(location,
ST_SRID(POINT(32.85, 39.92), 4326)) AS distance
FROM shop
ORDER BY distance LIMIT 10;MySQL(5.7+)은 OGC 표준 공간 데이터 타입(POINT, POLYGON 등)과 ST_ 함수를 지원한다. SPATIAL 인덱스(R-tree)는 InnoDB/MyISAM과 NOT NULL 컬럼에서만 생성할 수 있으며, 옵티마이저가 사용하려면 컬럼이 SRID 속성(SRID 4326)으로 정의되어야 한다. SRID 4326에서 ST_Distance는 측지 거리를 미터 단위로 반환한다. POINT(x, y) + ST_SRID에서 x는 경도, y는 위도이며, SRID 4326의 WKT 입력(ST_GeomFromText)에서는 위도-경도 순서다.
SQL Server
-- geography type and spatial index:
CREATE SPATIAL INDEX location_sidx ON dbo.shop(location);
-- Shops within 5 km (STDistance returns meters):
SELECT name FROM dbo.shop
WHERE location.STDistance(
geography::Point(39.92, 32.85, 4326)) <= 5000;SQL Server는 두 가지 공간 타입을 제공한다: geography(구면, 위도/경도)와 geometry(평면). STDistance, STIntersects, STContains 같은 메서드가 쿼리를 처리한다. 공간 인덱스(그리드 기반)가 성능을 높인다. geography::Point(latitude, longitude, SRID)의 인수 순서에 유의한다.
MongoDB
// 2dsphere index (for GeoJSON):
db.shop.createIndex({ location: "2dsphere" })
// Shops nearest to a given point ($near):
db.shop.find({
location: {
$near: {
$geometry: { type: "Point", coordinates: [32.85, 39.92] },
$maxDistance: 5000
}
}
})MongoDB는 지리 데이터를 GeoJSON 형식으로 저장하고 2dsphere 인덱스로 구면 쿼리를 실행한다. $near(거리순 정렬), $geoWithin(영역 내), $geoIntersects 연산자를 지원한다. 좌표는 [경도, 위도] 순서이며, $maxDistance는 미터 단위다.
Redis
# Built-in geospatial commands (built on sorted sets):
GEOADD shops 32.85 39.92 "kizilay"
GEOADD shops 32.86 39.93 "cankaya"
# Search within 5 km of a point:
GEOSEARCH shops FROMLONLAT 32.85 39.92
BYRADIUS 5 km ASCRedis는 GEOADD(longitude latitude member)로 지리적 위치를 Sorted Set에 저장한다. GEOSEARCH(Redis 6.2+, 기존 GEORADIUS 대체)는 반경 또는 박스 안의 멤버를 거리순으로 반환한다. GEODIST는 두 지점 간 거리를 보여 준다. 기본 기능이므로 모듈이 필요 없다.
Elasticsearch
# Map the field as geo_point:
PUT shop
{ "mappings": { "properties": { "location": { "type": "geo_point" } } } }
# Query within 5 km:
GET shop/_search
{ "query": { "geo_distance": {
"distance": "5km",
"location": { "lat": 39.92, "lon": 32.85 } } } }Elasticsearch는 geo_point(점)와 geo_shape(다각형/선) 필드 타입을 지원한다. 필터링은 geo_distance(반경), geo_bounding_box(박스), geo_polygon 쿼리로, 정렬은 geo_distance로, 집계는 geohash_grid/geotile_grid로 수행한다. 좌표는 lat/lon 또는 [lon, lat] 배열로 지정한다.