본문 바로가기
Database/MYSQL

Mysql / Mariadb 공간 데이터베이스

by 반화넬 2024. 7. 29.
반응형

 

 

  쉽게 설명하면 X, Y 좌표로 구성된 공간 데이터를 저장하고 연산할 수 있는 기능을 제공해주는 데이터베이스라고 생각하시면 됩니다. 다른 말로, 공간 데이터의 저장 형태를 구분하는 공간 데이터 타입과 공간 데이터를 연산할 수 있는 공간 함수가 제공되는 데이터베이스라고 표현 가능합니다.

 

  우리가 일반적으로 사용하고 있는 RDBMS인 Oracle, MariaDB, MySQL, PostgreSQL 등에서 공간 데이터를 처리하기 위한 기능을 제공하고 있습니다. 이 솔루션을 이용해 공간 데이터베이스를 생성/관리할 수 있는 겁니다. 심지어 Hive에서도 관련 Library를 설치하면 공간 데이터를 저장하고 공간 연산이 가능합니다.

 

  그럼, 공간 데이터 타입과 공간 함수를 알면 공간 데이터베이스를 정복하게 되는걸까요? 저는 그렇다고 생각합니다. 가장 기본적인 공간 데이터 타입과 공간 함수를 알면 쉽게 공간 데이터를 처리할 수 있으니까요. 가장 기본적인 기초만 알면 그 후의 응용문제는 쉽게 풀어갈 수 있다고 생각합니다.

 

  참고로, 공간 데이터 타입과 함수는 Open Geospatial Consortium(OGC, www.ogc.org)에서 표준을 정의하고 있습니다. 아래 링크를 클릭하시면 표준 문서를 다운로드 하실 수 있습니다.


   > 표준 문서 다운로드 : http://portal.opengeospatial.org/files/?artifact_id=25354

 

  이제 공간 데이터베이스의 기초인 공간 데이터 타입에 대해 알아보겠습니다. 여기서는 MySQL에서 제공하는 공간 데이터 타입을 기준으로 설명을 진행할 것입니다.

  자주 사용되는 공간 데이터 타입은 아래와 같습니다.

공간 데이터 타입

 

 

공간데이터타입 정의 SQL 예
Point 좌표 공간에서 한 지점의 위치를 표시 POINT (10 10)
LineString 다수의 Point를 연결해주는 선분 LINESTRING (10 10, 20 25, 15 40)
Polygon 다수의 선분들이 연결되어 닫혀 있는 상태인 다각형 POLYGON ((10 10, 10 20, 20 20, 20 10, 10 10))
Multi-Point 다수 개의 Point 집합 MULTIPOINT (10 10, 30 20)
Multi-LineString 다수 개의 LineString 집합 MULTILINESTRING ((10 10, 20 20), (20 15, 30 40))
Multi-Polygon 다수 개의 Polygon 집합 MULTIPOLYGON ((( 10 10, 15 10, 20 15, 20 25, 15 20, 10 10 )) , (( 40 25, 50 40, 35 35, 25 10, 40 25 )) )
GeomCollection 모든 공간 데이터들의 집합 GEOMETRYCOLLECTION ( POINT (10 10), LINESTRING (20 20, 30 40), POINT (30 15) )

 

 

  MySQL에서 공간 데이터 타입의 컬럼을 추가하고, 공간 데이터를 입력해보도록 하겠습니다.

CREATE TABLE GEO_TAB
( 
  GID  INT(10),
  PT   POINT,
  LS   LINESTRING
);

  위 SQL은 테스트용 테이블 GEO_TAB을 생성하는 DDL문입니다. GEO_TAB 테이블은 일반 INT형 GID 컬럼, POINT 공간데이터 타입인 PT 컬럼과 LINESTRING 공간데이터 타입인 LS 컬럼으로 구성됩니다.

  이제 위에서 생성한 GEO_TAB 테이블에 데이터를 입력해보도록 하겠습니다. 

SET @g1 = 'POINT(10 10)';
SET @g2 = GeomFromText( 'LINESTRING(5 5, 10 5, 15 10)' );
INSERT INTO GEO_TAB VALUES ( 1, GeomFromText(@g1), @g2 );

  데이터 입력 예제의 가독성을 위해 사용자 변수를 사용하여 데이터를 입력해보았습니다.
  사용자변수 g1에는 POINT형 공간 데이터를 입력하기 위한 공간 데이터 문자열을 저장합니다. 사용자 변수 g2에는 LINESTRING형 공간 데이터를 저장합니다.
  이 사용자 변수의 값을 GEO_TAB 테이블에 입력을하는데 공간 데이터의 입력도 일반 RDBMS처럼 INSERT문을 사용합니다.
  이 때, 공간 데이터 타입은 Binary 형태로 저장되기 때문에 문자열을 저장한 사용자 변수 g1은 공간 데이터 타입으로 변환해주는 GeomFromText 함수를 사용하여 Binary로 변환 후 저장해야 합니다.
(* GeomFromText 함수는 MySQl 8.0에서 Remove되었으며, ST_GeomFromText 함수를 사용하면 됩니다. )

  공간 데이터를 조회하기 위해서는 Binary 데이터를 텍스트로 변환하는 AsText함수를 사용하면 됩니다.
(* AsText 함수는 MySQl 8.0에서 Remove되었으며, ST_AsText 함수를 사용하면 됩니다. )

SELECT GID, AsText(PT), AsText(LS) FROM GEO_TAB; 

 

  아래 그림은 MySQL에서 테스트한 결과 화면입니다.

 

 

 

출처 : https://sparkdia.tistory.com/24?category=1114027 

 

 

 

#  추가 설명 

 

MySQL 의 SPATIAL 데이터중, 폴리곤 데이터를 Insert 쿼리.

 

x,y 좌표를 순서대로 입력해주면 되는데, 시작과 끝은 똑같은 값이다. (시작과 끝이 만나야하기 때문에...)

INSERT INTO mytable(poly) VALUES(POLYGONFROMTEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))'))

 

 

- 한 점을 가지고, 폴리곤 영역안에 포함되어있는 레코드를 Select 해오기.

SELECT name, AsWKT(poly) AS poly FROM mytable WHERE MBRContains(poly, GeomFromText('Point(1 1)'))


출처 : https://kokohapps.tistory.com/entry/MySQL-Polygon-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9E%85%EB%A0%A5%ED%95%98%EA%B8%B0

 

요즘엔 위치 기반의 서비스가 많이 있어 사용자의 위치로부터 가까운 곳에 맛집을 찾아 준다거나 혹은 원하는 장소를 가까운 순으로 정렬해서 보여주는 경우가 많이 있어요. 예를 들어 맛집 정보가 데이터베이스 테이블에 위도, 경도 정보와 함께 저장이 되는데 내 위치의 위도, 경도 정보와 비교하여 가까운 순으로 정렬을 하려면 어떻게 해야 할까요? 이를 지원하는 기능이 Spatial SQL 입니다. Special(특별한) 아니고요, Spatial(공간적인) SQL 입니다. MySQL은 Spatial SQL을 5.7 버전부터 지원하기 시작하였고요, 현재 최신 버전인 8.x 사용을 권장합니다.

우선 Spatial Query를 사용하기 위해서 테이블을 만들고 위도, 경도를 저장할 컬럼을 생성해야 겠죠. 아래와 같이 POINT라는 타입의 컬럼은 위도, 경도로 표현되는 위치 값을 저장할 수 있습니다. 물론 INDEX도 걸어줄 수 있고요. INDEX를 걸어 주어야 위치 정보를 가지고 검색이나 정렬이 빠르겠죠.

CREATE TABLE ItemInfo (
itemId VARCHAR(128) PRIMARY KEY,
title VARCHAR(128) NOT NULL DEFAULT '',
description VARCHAR(4096),
location POINT NOT NULL,
INDEX index_location (location)
);
테이블에 위도, 경도를 POINT 형태로 변환하여 입력하려면 아래와 같이 POINT() 함수로 경도, 위도를 묶어 주면 됩니다. 순서가 반드시 경도 -> 위도 순서입니다.

INSERT INTO ItemInfo(itemId, title, description, location) VALUES(100, '마곡 삼계탕', '직장인 점심식사 최고에요', POINT(127.0243, 36.5434))
테이블에 저장된 POINT 형태의 값을 위도, 경도로 변환해서 읽으려면 아래와 같이 ST_X, ST_Y 함수를 사용하면 됩니다.

SELECT *, ST_X(location) AS longitude, ST_Y(location) AS latitude FROM ItemInfo;
만약 내 위치()를 기준으로 가까운 순으로 목록을 가져오려면 어떻게 해야 할까요? ST_DISTANCE_SPHERE()라는 함수는 파라미터로 전달된 두 지점(POINT 타입)의 거리를 계산하는 함수입니다. 아래의 예처럼 이 결과를 가지고 정렬(ORDER BY)하면 됩니다.

SELECT *, ST_DISTANCE_SPHERE(POINT(128.5434, 37.6512), location) AS distance FROM ItemInfo ORDER BY distance
또한 특정 구역을 폴리곤으로 구성하여 이 구역 내에 있는 항목만 가져올 수도 있습니다.

SELECT * FROM ItemInfo WHERE MBRContains(ST_GeomFromText('Polygon((0 0, 0 3, 3 3, 3 0, 0 0))'), location)
Polygon 안의 파라미터는 각 점들의 X Y 값을 컴마로 이어 만든 폴리곤 값인데요, 자바라면 아래와 같이 앱에서 만들어 낼 수 있습니다. 
만약 사각형 영역(좌상단 x1, y1 이고 우하단이 x2, y2라면)에 대해 Polygon 텍스트는 아래와 같이 만들어 낼 수 있습니다.

x,y 좌표를 순서대로 입력해주면 되는데, 시작과 끝은 똑같은 값이다.
> 시작점 A : top left
> 두번째점 B : bottom left
> 세번째점 C : bottom right
> 네번째점 D : top right
> 다시 원점 A : top left

String polygon = "Polygon((" + x1 + " " + y1 + ", " + x2 + " " + y1 + ", " + x2 + " " + y2 + ", " + x1 + " " + y2 + ", " + x1 + " " + y1 + "))";
이런식으로 MBR...이라는 이름으로 시작하는 함수는 각 구역과 위치에 대한 다양한 함수를 제공하는데 MBR은 Minimum Bounding Rectangle의 약자입니다.

​MySQL이 지원하는 Spatial SQL에 대해 좀 더 알고 싶다면 POINT, ST_xxx, MBRxxx 이러한 키워드로 검색해 보시면 됩니다.

반응형