Contents
1. はじめに
Google BigQuery が提供する GEOGRAPHY データ型は、空間分析を行う際の唯一の前提条件です。本稿では、以下のポイントを中心に解説します。
- GEOGRAPHY 型とその測地系(WGS‑84)の基本概念
- CSV・GeoJSON・Parquet などからのデータ取り込み手順
- 主な GIS 関数と実装例
- 公開データセット Citi Bike を使ったハンズオン
- パフォーマンス最適化と可視化のベストプラクティス
本記事は公式ドキュメントを基に作成していますが、Qiita 記事(非公式)を参照した箇所は明示的に区別しています。
2. GEOGRAPHY データ型と WGS‑84 測地系
| 項目 | 内容 |
|---|---|
| データ型 | GEOGRAPHY(緯度・経度のペア) |
| 内部表現 | Well‑Known Text (WKT) または EWKB で保存し、BigQuery が自動的に最適化 |
| サポートジオメトリ | POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON, GEOMETRYCOLLECTION(3D は未対応) |
| 測地系 | 常に WGS‑84 (World Geodetic System 1984) が使用され、座標変換は不要 |
WGS‑84 は GPS でも採用されている国際的な楕円体です。関数によっては「球面」(
sphere) と「楕円体」(spheroid) のどちらで距離を計算するかをオプションで選択できますが、測地系自体は常に WGS‑84 です【公式ドキュメント】(https://cloud.google.com/bigquery/docs/geospatial-data?hl=ja)。
2‑1. 代表的な構文例
|
1 2 3 4 5 6 |
-- POINT を作成(経度, 緯度 の順) SELECT ST_GEOGPOINT(-73.9857, 40.7484) AS empire_state; -- WKT 文字列から GEOGRAPHY に変換 SELECT ST_GeogFromText('POINT(-73.9857 40.7484)') AS geom; |
3. 空間データのインポート方法
3‑1. スキーマ定義は必須
外部ストレージ(Cloud Storage 等)からロードする場合、GEOGRAPHY カラムを 明示的に スキーマで指定します。
|
1 2 3 4 |
# テーブル作成例(station_id, name は文字列、location が GEOGRAPHY) bq mk --table my_dataset.citibike_stations \ station_id:STRING,name:STRING,location:GEOGRAPHY |
3‑2. CSV/GeoJSON の取り込み
CSV に lon,lat 形式の文字列があるケースを例にします。
|
1 2 3 4 5 6 7 8 |
# CSV を Cloud Storage にアップロード gsutil cp stations.csv gs://my-bucket/ # ロード(location は文字列として取得) bq load --source_format=CSV \ my_dataset.citibike_stations gs://my-bucket/stations.csv \ station_id,name,location |
3‑2‑1. 文字列 → GEOGRAPHY への変換
|
1 2 3 4 5 6 |
UPDATE my_dataset.citibike_stations SET location = ST_GEOGPOINT( CAST(SPLIT(location, ',')[OFFSET(0)] AS FLOAT64), CAST(SPLIT(location, ',')[OFFSET(1)] AS FLOAT64)) WHERE TRUE; |
3‑3. Parquet の取り込み
Parquet ファイルに WKT 文字列で GEOGRAPHY カラムを保存しておけば、スキーマだけ指定すればそのままロードできます。
|
1 2 3 4 |
bq load --source_format=PARQUET \ my_dataset.parquet_table gs://my-bucket/data.parquet \ --schema location:GEOGRAPHY,station_id:STRING,name:STRING |
注意:Qiita 記事(例:https://qiita.com/shin_ishiguro/items/2429038b2c4c99c10837)は実装サンプルとして有用ですが、公式情報ではありません。最新の仕様は必ず Google Cloud のドキュメントをご確認ください。
4. 主な GIS 関数と使用例
| 関数 | 説明 | サンプル |
|---|---|---|
ST_GEOGPOINT(lon, lat) |
点オブジェクト作成 | SELECT ST_GEOGPOINT(-73.9857, 40.7484) AS pt; |
ST_GeogFromText(wkt) |
WKT → GEOGRAPHY 変換 | SELECT ST_GeogFromText('POINT(-73.9857 40.7484)'); |
ST_DISTANCE(g1, g2[, spheroid]) |
2点間距離(メートル) ※ spheroid=TRUEで楕円体計算 |
SELECT ST_DISTANCE(ptA, ptB) AS d; |
ST_WITHIN(point, polygon) |
点がポリゴン内か判定 | SELECT ST_WITHIN(p, poly) FROM …; |
ST_INTERSECTS(g1, g2) |
ジオメトリ同士の交差判定 | SELECT ST_INTERSECTS(line, poly); |
ST_BUFFER(geog, radius_meters) |
指定半径でバッファー(円)作成 | SELECT ST_BUFFER(pt, 500) AS buf; |
4‑1. 距離検索の実装例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
WITH stations AS ( SELECT station_id, name, ST_GEOGPOINT(longitude, latitude) AS geom FROM `bigquery-public-data.new_york.citibike_stations` ) SELECT station_id, name, ROUND(ST_DISTANCE(geom, ST_GEOGPOINT(-73.9857, 40.7484)), 0) AS distance_m FROM stations WHERE ST_DISTANCE(geom, ST_GEOGPOINT(-73.9857, 40.7484)) <= 500 ORDER BY distance_m; |
5. ハンズオン – Citi Bike データセットで学ぶ
5‑1. データ概要(公式公開データセット)
| フィールド | 型 | 説明 |
|---|---|---|
station_id |
STRING | ステーション ID |
name |
STRING | 駅名 |
latitude |
FLOAT64 | 緯度 |
longitude |
FLOAT64 | 経度 |
5‑2. ポリゴン内判定(Manhattan 区域)
以下は別テーブルに保存した行政区画ポリゴンを利用する例です。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
WITH stations AS ( SELECT station_id, name, ST_GEOGPOINT(longitude, latitude) AS geom FROM `bigquery-public-data.new_york.citibike_stations` ), manhattan AS ( SELECT poly FROM `my_dataset.nyc_admin_zones` WHERE zone_name = 'Manhattan' ) SELECT s.station_id, s.name FROM stations s, manhattan m WHERE ST_WITHIN(s.geom, m.poly); |
ポイント:
ST_GEOGPOINTによる変換とST_DISTANCE / ST_WITHINの組み合わせだけで、実務レベルの空間検索が完結します。自社データでも同様に適用可能です。
6. パフォーマンス最適化と可視化ベストプラクティス
6‑1. クラスタ化テーブルによるスキャン削減
GEOGRAPHY カラムを クラスタキー に指定すると、同一領域のレコードが物理的に近く格納され、空間フィルタ(例:ST_DISTANCE < 1000)のスキャンバイトが大幅に削減されます。
|
1 2 3 4 5 6 7 8 |
CREATE TABLE my_dataset.citibike_clustered PARTITION BY DATE(_PARTITIONTIME) CLUSTER BY location AS SELECT station_id, name, ST_GEOGPOINT(longitude, latitude) AS location FROM `bigquery-public-data.new_york.citibike_stations`; |
実測例は 2023 年 5 月に公開された Google Cloud Blog(BigQuery GIS のパフォーマンス最適化)で報告されており、同様のクラスタ化テーブルではスキャンバイトが約 30 % 削減されたと記載されています。
6‑2. サンプリングによる試行コスト削減
クエリ開発段階では TABLESAMPLE SYSTEM (10 PERCENT) を併用し、データ量を抑えて高速に結果を確認できます。
|
1 2 3 4 5 |
SELECT * FROM my_dataset.citibike_clustered TABLESAMPLE SYSTEM (10 PERCENT) WHERE ST_DISTANCE(location, ST_GEOGPOINT(-73.9857, 40.7484)) < 1000; |
6‑3. 可視化へのエクスポート
| ツール | 手順概要 |
|---|---|
| Looker Studio | データソースにテーブルを接続し、location を「ジオメトリ」タイプとして設定。マップウィジェットで ST_BUFFER(location, 500) の結果を表示すれば検索半径が可視化できます。 |
| Google Maps API | クエリ結果(WKT または GeoJSON)を Cloud Storage に書き出し、gsutil cp で取得後、JavaScript の new google.maps.Data().addGeoJson() でマップ上に描画可能です。 |
7. 参考情報・リンク
| 内容 | URL |
|---|---|
| BigQuery GIS 公式ドキュメント(日本語) | https://cloud.google.com/bigquery/docs/geospatial-data?hl=ja |
| GIS 関数リファレンス | https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#geography_functions |
| パフォーマンスに関する公式ブログ(英語) | https://cloud.google.com/blog/products/data-analytics/bigquery-spatial-performance |
| Qiita 記事(非公式サンプル)※参考程度 | https://qiita.com/shin_ishiguro/items/2429038b2c4c99c10837 |
補足:Qiita の記事は個人の実装例であり、将来的に仕様が変わる可能性があります。必ず公式ドキュメントと併せて確認してください。
8. まとめ
- GEOGRAPHY + WGS‑84 が BigQuery GIS の唯一の前提条件です。測地系は固定なので座標変換は不要です。
- CSV・GeoJSON・Parquet からは
bq loadとスキーマ定義で簡単に取り込み、ST_GEOGPOINT/ST_GeogFromTextにより即時利用できます。 - 主な GIS 関数(
ST_GEOGPOINT,ST_DISTANCE,ST_WITHIN,ST_INTERSECTS,ST_BUFFER)はシンプルかつ高速に動作し、spheroid=TRUEオプションで楕円体計算も可能です。 - Citi Bike データセットを使ったハンズオンは、距離検索・領域判定の実装フローを具体的に示す良い教材となります。
- パフォーマンスは クラスタ化テーブル + サンプリング で最適化し、結果は Looker Studio や Google Maps API にエクスポートしてステークホルダーへ可視化できます。
これらの知見を活用すれば、BigQuery GIS を自社プロジェクトに即座に組み込み、コスト効率よく高度な空間分析が実現できるでしょう。