BigQuery GIS 데이터 작업

BigQuery GIS를 사용하면 BigQuery에서 지리 데이터를 분석할 수 있습니다. 지리 데이터는 지리정보 데이터라고도 합니다.

지리정보 데이터를 사용하여 작업할 때 일반적인 유형의 객체는 다음과 같습니다.

  • 도형은 지구의 표면적을 나타냅니다. 이는 보통 점, 선, 다각형 또는 점, 선, 다각형 컬렉션을 사용하여 기술합니다. 도형 컬렉션은 컬렉션에 있는 모든 모양의 공간 집합을 나타내는 도형입니다.
  • 공간 지형지물은 논리적 공간 객체를 나타냅니다. 이 속성은 도형을 애플리케이션별 추가 속성과 결합합니다.
  • 공간 특징 컬렉션은 공간 특징의 집합입니다.

BigQuery에서 GEOGRAPHY 데이터 유형은 도형 값 또는 도형 컬렉션을 나타냅니다. 공간 특성을 표현하려면 도형의 GEOGRAPHY 열과 속성의 추가 열을 사용하여 테이블을 만듭니다. 테이블의 각 행은 공간 특성이며 전체 테이블은 공간 특성 컬렉션을 나타냅니다.

GEOGRAPHY 데이터 유형은 지구 표면의 점 집합을 설명합니다. 점 집합은 에지(측지선)를 포함한 WGS84 기준 회전 타원체상의 점, 선, 다각형으로 구성된 집합입니다. 표준 SQL geography 함수 중 하나를 호출하여 GEOGRAPHY 데이터 유형을 사용할 수 있습니다.

지리정보 데이터 로드

지구상의 한 점을 간단하게 (longitude, latitude) 쌍으로 나타낼 수 있습니다. 예를 들어 경도 및 위도 값이 포함된 CSV 파일을 로드한 다음 ST_GEOGPOINT 함수를 사용하여 이를 GEOGRAPHY 값으로 변환할 수 있습니다.

보다 복잡한 지리의 경우 다음과 같은 지리공간 데이터 형식을 GEOGRAPHY 열에 로드할 수 있습니다.

  • WKT(Well Known Text)
  • WKB(Well-Known Binary)
  • GeoJSON

WKT 또는 WKB 데이터 로드

WKT는 점, 선, 다각형(선택사항으로 구멍이 있을 수 있음)이나 점, 선, 다각형 컬렉션을 사용하여 개별 도형 모양을 기술하는 텍스트 형식입니다. WKB는 WKT 형식의 바이너리 버전입니다.

예를 들어 다음은 WKT에서 점을 정의합니다.

POINT(-121 41)

공간 지형지물을 설명하기 위해 WKT는 일반적으로 CSV 파일 또는 데이터베이스 테이블에 포함된 컨테이너 파일 형식으로 삽입됩니다. 파일 행 또는 테이블 행은 일반적으로 공간 지형지물에 해당합니다. 전체 파일 또는 전체 테이블은 지형지물 컬렉션에 해당합니다. WKT 데이터를 BigQuery로 로드하려면 지리정보 데이터의 GEOGRAPHY 열을 지정하는 스키마를 제공합니다.

예를 들어 다음 데이터가 포함된 CSV 파일이 있다고 가정해 보겠습니다.

"POLYGON((-124.49 47.35,-124.49 40.73,-116.49 40.73,-116.49 47.35,-124.49 47.35))",poly1
"POLYGON((-85.6 31.66,-85.6 24.29,-78.22 24.29,-78.22 31.66,-85.6 31.66))",poly2
"POINT(1 2)",point1

bq 명령줄 도구 load 명령어를 실행하여 이 파일을 로드할 수 있습니다.

bq load --source_format=CSV \
  --schema="geography:GEOGRAPHY,name:STRING" \
  mydataset.mytable filename1.csv

BigQuery에서 데이터를 로드하는 방법에 대한 자세한 내용은 데이터 로드 소개를 참조하세요.

WKT 데이터를 GEOGRAPHY 열이 있는 기존 BigQuery 테이블로 스트리밍하려면 API 요청에서 데이터를 문자열로 직렬화합니다.

bq

bq 명령줄 도구 insert 명령어를 실행합니다.

echo '{"geo": "LINESTRING (-118.4085 33.9416, -73.7781 40.6413)"}' \
    | bq insert my_dataset.geo_table

Python

이 샘플을 사용해 보기 전에 BigQuery 빠른 시작: 클라이언트 라이브러리 사용의 Python 설정 안내를 따르세요. 자세한 내용은 BigQuery Python API 참조 문서를 확인하세요.

from google.cloud import bigquery
import shapely.geometry
import shapely.wkt

bigquery_client = bigquery.Client()

# This example uses a table containing a column named "geo" with the
# GEOGRAPHY data type.
table_id = "my-project.my_dataset.my_table"

# Use the Shapely library to generate WKT of a line from LAX to
# JFK airports. Alternatively, you may define WKT data directly.
my_geography = shapely.geometry.LineString(
    [(-118.4085, 33.9416), (-73.7781, 40.6413)]
)
rows = [
    # Convert data into a WKT string.
    {"geo": shapely.wkt.dumps(my_geography)},
]

#  table already exists and has a column
# named "geo" with data type GEOGRAPHY.
errors = bigquery_client.insert_rows_json(table_id, rows)
if errors:
    raise RuntimeError(f"row insert failed: {errors}")
else:
    print(f"wrote 1 row to {table_id}")

BigQuery의 데이터 스트리밍에 대한 자세한 내용은 BigQuery로 데이터 스트리밍을 참조하세요.

또한 ST_GeogFromText 함수를 사용하여 WKT 텍스트 문자열을 GEOGRAPHY 값으로 변환할 수도 있습니다.

GeoJSON 데이터 로드

GeoJSON은 도형 및 공간 지형지물을 위한 JSON 기반 형식입니다. 예를 들어 다음은 GeoJSON에서 점을 정의합니다.

{ "type": "Point", "coordinates": [-121,41] }

GeoJSON 데이터에는 다음과 같은 객체 유형이 포함될 수 있습니다.

  • 도형 객체. 도형 객체는 점, 선, 다각형(선택사항으로 구멍이 있을 수 있는 다각형)으로 설명된 공간 셰이프입니다.
  • 특성 객체. 지형지물 객체에는 도형과 추가 이름/값 쌍이 포함되어 있으며, 이는 애플리케이션별입니다.
  • 기능 항목 공간 지형지물 컬렉션은 지형지물 객체의 집합입니다.

BigQuery GIS는 다른 파일 유형에 삽입된 개별 GeoJSON 도형 객체 로드를 지원합니다. 예를 들어 열 중 하나에 GeoJSON 도형 객체가 포함된 CSV 파일을 로드할 수 있습니다.

BigQuery GIS는 GeoJSON 지형지물 객체, 지형지물 컬렉션, GeoJSON 파일 형식 로드를 지원하지 않습니다.

GeoJSON 데이터를 BigQuery로 로드하려면 GeoJSON 데이터의 GEOGRAPHY 열을 지정하는 스키마를 제공합니다. 데이터 객체가 줄바꿈으로 구분된 JSON 파일인 경우에도 도형 객체를 JSON 객체가 아닌 텍스트 문자열로 포맷합니다.

GeoJSON 데이터를 GEOGRAPHY 열이 있는 기존 BigQuery 테이블로 스트리밍하려면 API 요청에서 데이터를 문자열로 직렬화합니다.

bq

bq 명령줄 도구 insert 명령어를 실행합니다.

echo '{"geo": "{\"type\": \"LineString\", \"coordinates\": [[-118.4085, 33.9416], [-73.7781, 40.6413]]}"}' \
  | bq insert my_dataset.geo_table

Python

이 샘플을 사용해 보기 전에 BigQuery 빠른 시작: 클라이언트 라이브러리 사용의 Python 설정 안내를 따르세요. 자세한 내용은 BigQuery Python API 참조 문서를 확인하세요.

import geojson
from google.cloud import bigquery

bigquery_client = bigquery.Client()

# This example uses a table containing a column named "geo" with the
# GEOGRAPHY data type.
table_id = "my-project.my_dataset.my_table"

# Use the python-geojson library to generate GeoJSON of a line from LAX to
# JFK airports. Alternatively, you may define GeoJSON data directly, but it
# must be converted to a string before loading it into BigQuery.
my_geography = geojson.LineString([(-118.4085, 33.9416), (-73.7781, 40.6413)])
rows = [
    # Convert GeoJSON data into a string.
    {"geo": geojson.dumps(my_geography)}
]

#  table already exists and has a column
# named "geo" with data type GEOGRAPHY.
errors = bigquery_client.insert_rows_json(table_id, rows)
if errors:
    raise RuntimeError(f"row insert failed: {errors}")
else:
    print(f"wrote 1 row to {table_id}")

또한 ST_GEOGFROMGEOJSON 함수를 사용하여 GeoJSON 도형 객체를 GEOGRAPHY 값으로 변환할 수 있습니다.

좌표계와 에지

BigQuery GIS에서 점은 WGS84 회전 타원체의 표면상 위치입니다(경도+측지 위도로 표현). 에지는 두 엔드포인트 간의 구체 측지선입니다. 즉, 모서리는 구의 표면에서 가장 짧은 경로입니다.

WKT 형식은 좌표계를 제공하지 않습니다. WKT 데이터를 로드할 때 BigQuery GIS는 데이터가 구식 에지와 함께 WGS84 좌표를 사용한다고 가정합니다. 도형이 구면과 평면 가장자리의 차이가 무시될 수 있을 정도로 작은 경우가 아니라면 소스 데이터가 해당 좌표계와 일치하는지 확인합니다.

GeoJSON은 명시적으로 평면 에지가 있는 WGS84 좌표를 사용합니다. GeoJSON 데이터를 로드할 때 BigQuery GIS는 평면 가장자리를 구형 에지로 변환합니다. BigQuery GIS는 필요한 경우 선에 별도의 점을 추가하여 변환된 일련의 에지가 원래의 선으로부터 10미터 이내에 유지되도록 합니다. 이러한 프로세스를 테셀링 또는 균일하지 않은 고밀도화라고 합니다. 사용자가 공간 분할 프로세스를 직접 제어할 수 없습니다.

구면 에지가 있는 지리를 로드하려면 WKT를 사용합니다. 평면 에지가 있는 지리(geomeries라고도 함)를 로드하려면 GeoJSON을 사용하는 것이 가장 간단합니다. 그러나 도형 데이터가 이미 WKT 형식인 경우 또 다른 옵션으로는 데이터를 STRING 유형으로 로드한 다음 ST_GEOGFROMTEXT 함수를 사용하여 GEOGRAPHY 값으로 변환하는 방법이 있습니다. planar 매개변수를 TRUE로 설정하여 데이터를 평면으로 해석합니다.

교차 형식 선택 시 소스 데이터에 사용되는 좌표계를 알아야 합니다. 대부분의 시스템은 WKT에서 (지형이 아닌) 지리의 파싱을 명시적으로 지원하며, 그렇지 않은 경우 평면 에지라고 가정합니다.

좌표에서는 경도가 첫 번째 형식이고, 위도가 두 번째 형식이어야 합니다. 지리에 긴 세그먼트 또는 에지가 있으면 BigQuery GIS에서 이를 구면 측지선으로 해석하지만 이 값이 데이터의 출처인 좌표계에 대응하지 않을 수 있으므로 공간 분할이 적용되어야 합니다.

다각형 방향

구체의 각 다각형에는 보완 다각형이 있습니다. 예를 들어 지구의 대륙을 나타내는 다각형에는 지구의 대양을 나타내는 보완 다각형이 있습니다. 두 다각형은 동일한 경계 링으로 표현되므로 특정 WKT 문자열이 나타내는 다각형이 둘 중 무엇인지를 확실히 알려주는 규칙이 필요합니다.

개발자가 파일에서 직접 또는 스트리밍 수집을 통해 WKT 및 WKB 문자열을 로드할 때 다각형의 경계를 입력 카테고리 순서로 순회하면 BigQuery GIS는 입력된 다각형의 왼쪽이 내부라고 가정합니다. BigQuery GIS는 WKT 및 WKB 문자열로 지리 객체를 내보낼 때도 동일한 규칙을 사용합니다.

ST_GeogFromText 함수를 사용하여 WKT 문자열을 GEOGRAPHY 값으로 변환하는 경우 oriented 매개변수는 함수가 다각형을 결정하는 방식을 지정합니다.

  • FALSE: 면적이 더 작은 다각형으로 입력을 해석합니다. 기본적으로 설정되어 있습니다.

  • TRUE: 앞에서 설명한 왼쪽 방향 규칙을 사용합니다. 이 옵션을 사용하면 반구보다 면적이 더 큰 다각형을 로드할 수 있습니다.

GeoJSON 문자열은 평면 지도에 정의되므로 입력이 GeoJSON 형식 사양 RFC 7946에 정의된 방향 규칙을 따르지 않더라도 모호 없이 방향을 결정할 수 있습니다.

부적절한 형식의 공간 데이터 처리

다른 도구의 공간 데이터를 BigQuery로 로드하면 잘못된 WKT 또는 GeoJSON 데이터로 인해 변환 오류가 발생할 수 있습니다. 예를 들어 Edge K has duplicate vertex with edge N 같은 오류는 다각형에 첫 번째와 마지막 교점 외에 중복된 교점이 존재함을 나타냅니다.

형식 지정 문제를 방지하려면 표준을 준수하는 결과를 생성하는 함수를 사용합니다. 예를 들어 PostGIS에서 데이터를 내보낼 때 PostGIS ST_MakeValid 함수를 사용하여 출력을 표준화할 수 있습니다. 또는 데이터를 텍스트로 가져온 다음 make_valid 매개변수로 ST_GEOGFROMTEXT 또는 ST_GEOGFROMGEOJSON를 호출하여 변환합니다. make_validTRUE이면 이러한 함수는 잘못된 다각형 복구를 시도합니다.

부적절한 형식의 데이터를 찾거나 무시하려면 SAFE 함수 프리픽스를 사용하여 문제가 있는 데이터를 출력합니다. 예를 들어 다음 쿼리는 SAFE 프리픽스를 사용하여 부적절한 형식의 공간 데이터를 검색합니다.

SELECT
  geojson AS bad_geojson
FROM
  mytable
WHERE
  geojson IS NOT NULL
  AND SAFE.ST_GeogFromGeoJson(geojson) IS NULL

제약조건

BigQuery GIS는 공간 형식의 다음 지형지물을 지원하지 않습니다.

  • 3차원 도형. 여기에는 WKT 형식의 'Z' 서픽스와 GeoJSON 형식의 고도 좌표가 포함됩니다.
  • 선형 참조 시스템. 여기에는 WKT 형식의 'M' 서픽스가 포함됩니다.
  • 기본 도형 또는 멀티파트 도형 이외의 WKT 도형 객체. 특히 BigQuery GIS는 Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, GeometryCollection만 지원합니다.

GeoJson 및 WKT 입력 형식과 관련된 제약조건은 ST_GeogFromGeoJsonST_GeogFromText를 참조하세요.

BigQuery GIS 데이터 변환

테이블에 별도의 경도와 위도 열이 포함되어 있으면 ST_GeogPoint와 같은 표준 SQL 지리 함수를 사용하여 값을 지리정보로 변환할 수 있습니다. 예를 들어 경도와 위도를 위한 두 개의 DOUBLE 열이 있으면 다음 쿼리를 사용하여 지리 열을 생성할 수 있습니다.

SELECT
  *,
  ST_GeogPoint(longitude, latitude) AS g
FROM
  mytable

BigQuery는 WKT와 GeoJSON 문자열을 지리 유형으로 변환할 수 있습니다. 데이터가 셰이프파일과 같은 다른 형식인 경우에는 외부 도구를 사용하여 데이터를 WKT 또는 GeoJSON 문자열로 인코딩된 GEOGRAPHY 열을 사용하여 CSV 파일과 같은 지원되는 입력 파일 형식으로 변환합니다.

BigQuery GIS 데이터 파티션 나누기 및 클러스터링

GEOGRAPHY 열이 포함된 테이블을 클러스터링하고 파티션을 나눌 수 있습니다. GEOGRAPHY 열을 클러스터링 열로 사용할 수 있지만 GEOGRAPHY 열을 파티션 나누기 열로 사용할 수 없습니다.

테이블에 GEOGRAPHY 데이터를 저장하고 쿼리가 공간 조건자를 사용하여 데이터를 필터링하는 경우 테이블이 GEOGRAPHY 열로 클러스터링되는지 확인합니다. 이렇게 하면 일반적으로 쿼리 성능이 향상되고 비용이 절감됩니다. 공간 조건자는 부울 지리 함수를 호출하고 GEOGRAPHY 열을 인수 중 하나로 사용합니다. 다음 샘플에서는 ST_DWithin 함수를 사용하는 공간 조건자를 보여줍니다.

WHERE ST_DWithin(geo, ST_GeogPoint(longitude, latitude), 100)

JOIN을 공간 데이터와 함께 사용

공간 JOIN은 WHERE 절에 조건자 지리 함수가 있는 두 테이블의 조인입니다. 예를 들면 다음과 같습니다.

-- how many stations within 1 mile range of each zip code?
SELECT
    zip_code AS zip,
    ANY_VALUE(zip_code_geom) AS polygon,
    COUNT(*) AS bike_stations
FROM
    `bigquery-public-data.new_york.citibike_stations` AS bike_stations,
    `bigquery-public-data.geo_us_boundaries.zip_codes` AS zip_codes
WHERE ST_DWithin(
         zip_codes.zip_code_geom,
         ST_GeogPoint(bike_stations.longitude, bike_stations.latitude),
         1609.34)
GROUP BY zip
ORDER BY bike_stations DESC

지리 데이터가 유지되면 공간 조인 성능이 향상됩니다. 위의 예는 쿼리의 지리 값을 생성합니다. 지리 값을 BigQuery 테이블에 저장하면 성능이 더 향상됩니다.

예를 들어 다음 쿼리는 경도와 위도 쌍을 검색하여 지리적 점으로 변환합니다. 이 쿼리를 실행하려면 쿼리 결과를 저장할 새로운 대상 테이블을 지정해야 합니다.

SELECT
  *,
  ST_GeogPoint(pLongitude, pLatitude) AS p
FROM
  mytable

BigQuery는 다음 표준 SQL 조건자 함수를 사용하여 INNER JOIN 연산자와 CROSS JOIN 연산자에 최적화된 공간 JOIN을 구현합니다.

다음과 같은 경우에는 공간 조인이 최적화되지 않습니다.

  • LEFT, RIGHT 또는 FULL OUTER 조인의 경우
  • ANTI 조인과 관련된 경우
  • 공간 조건자를 부정하는 경우

ST_DWithin 조건자를 사용하는 JOIN은 거리 매개변수가 상수 표현식일 때만 최적화됩니다.

공간 데이터 내보내기

BigQuery에서 공간 데이터를 내보낼 때 GEOGRAPHY 열은 형식이 항상 WKT 문자열로 지정됩니다. 데이터를 GeoJSON 형식으로 내보내려면 ST_AsGeoJSON 함수를 사용합니다.

내보낸 데이터를 분석하는 데 사용되는 도구가 GEOGRAPHY 데이터 유형을 인식하지 못하면 ST_AsText 또는 ST_AsGeoJSON과 같은 지리 함수를 사용하여 열 값을 문자열로 변환할 수 있습니다. BigQuery GIS는 필요한 경우 선에 별도의 점을 추가하여 변환된 일련의 에지가 원래의 측지선으로부터 10미터 이내에 유지되도록 합니다.

예를 들어 다음 쿼리는 ST_AsGeoJSON을 사용하여 GeoJSON 값을 문자열로 변환합니다.

SELECT
  ST_AsGeoJSON(ST_MakeLine(ST_GeogPoint(1,1), ST_GeogPoint(3,2)))

결과 데이터는 다음과 유사한 형태입니다.

{ "type": "LineString", "coordinates": [ [1, 1], [1.99977145571783, 1.50022838764041], [2.49981908082299, 1.75018082434274], [3, 2] ] }

GeoJSON 선에 두 개의 점이 추가되었습니다. BigQuery GIS는 이러한 점을 추가하여 GeoJSON 선이 지면에서 원래의 선과 동일한 경로를 밀접하게 따르도록 합니다.

다음 단계