Upgrade to Pro — share decks privately, control downloads, hide ads and more …

MySQLを使ってGPSデータを軌跡データへ変換する手法と、軌跡データの類似性比較手法 / f...

MySQLを使ってGPSデータを軌跡データへ変換する手法と、軌跡データの類似性比較手法 / foss4g-kyushu-2025

2025年8月9日(土)に開催された「FOSS4G KYUSHU 2025」での発表資料です。
https://foss4gtokai.my.canva.site/foss4g-kyushu-2025

MySQLを使ってGPSデータを軌跡データに変換する手法や、軌跡データの類似性を比較する手法などについて解説しています。

Avatar for YoshiakiYamasaki

YoshiakiYamasaki

August 09, 2025
Tweet

More Decks by YoshiakiYamasaki

Other Decks in Technology

Transcript

  1. • 名前︓⼭﨑 由章(やまさき よしあき) • 所属︓⽇本オラクル株式会社 MySQL Community Team /

    MySQL Global Business Unit • 役割︓MySQL 及び MySQL HeatWave の 普及促進活動、など • Twitter ID︓@yyamasaki1 • 出⾝地︓明⽯市(東経135度 ⼦午線を通るまち) • 趣味︓美味しいものを⾷べること、 ⾊々な所に⾏くこと、ボードゲーム、など ⾃⼰紹介 Copyright © 2025, Oracle and/or its affiliates 2
  2. MySQLのGIS機能の歴史 Copyright © 2025, Oracle and/or its affiliates 5 MySQL

    Sun 2000 2005 2010 2015 2020 Oracle 4.1.0 (2003) MyISAMに Spatial Extensions実装 5.0.16 (2005) InnoDBにも Spatial Extensions実装 8.0.0 (2016) 関数名をST_*系に統⼀ 関数を⼤幅に追加 回転楕円体としての演算 5.7.1 (2013) Spatial専⽤の型を実装 Boostライブラリを利⽤した 再実装 8.0.11 (2018) GAとなる 8.0.32 (2023) 座標系変換がほぼ 全ての座標系に対応
  3. • POINT︓点 • 例︓緯度、経度 • LINESTRING︓線 • 例︓ルート(道筋) • POLYGON︓多⾓形

    • 例︓市町村の区画 • GEOMETRY︓POINT、LINESTRING、POLYGONをまとめて扱える Copyright © 2025, Oracle and/or its affiliates 9 GISデータを格納するための専⽤のデータが型ある ※それぞれの集合を扱えるデータ型もある (MULTIPOINT、MULTILINESTRING、MULTIPOLYGON、GEOMETRYCOLLECTION)
  4. • テキストデータをGISデータに変換するための関数 • ST_GeomFromText() • ST_PointFromText() • ST_LineStringFromText() • ST_PolygonFromText()

    • ST_MultiPointFromText() • ST_MultiLineStringFromText() • ST_MultiPolygonFromText() • ST_GeometryCollectionFromText() Copyright © 2025, Oracle and/or its affiliates 10 GISデータを変換したり計算したりするための各種Spatial関数がある
  5. • GISデータをテキストデータに変換するための関数 • ST_AsText() Copyright © 2025, Oracle and/or its

    affiliates 11 GISデータを変換したり計算したりするための各種Spatial関数がある
  6. • GeoJSONデータをGISデータに変換するための関数 • ST_GeomFromGeoJSON() • GISデータをテキストデータに変換するための関数 • ST_AsGeoJSON() • 経度、緯度からGeohashを求めるための関数

    • ST_GeoHash() • Geohashをデコードし、デコードされたGeohash値を含むPOINTデータを返す関数 • ST_PointFromGeoHash() Copyright © 2025, Oracle and/or its affiliates 12 GeoJSONを扱うための関数、Geohashを扱うための関数もある
  7. • MySQL 8.4 Reference Manual / Spatial Function Reference https://dev.mysql.com/doc/refman/8.4/en/spatial-function-reference.html

    Copyright © 2025, Oracle and/or its affiliates 13 Spatial関数の⼀覧は、ドキュメントで確認できます
  8. • 時刻とGPSポイント(緯度経度)の情報を格納する列を含んだテーブルを作成する テーブル作成例) Copyright © 2025, Oracle and/or its affiliates

    16 1. GPSデータを格納するためのテーブルを作成する CREATE TABLE gps_points ( id INT AUTO_INCREMENT PRIMARY KEY, route_id INT NOT NULL, -- ルート識別⼦ timestamp DATETIME NOT NULL, -- GPSポイントが記録された時刻 (タイムスタンプ) geom POINT NOT NULL SRID 4326 -- GPSポイント (WGS84で格納) );
  9. 例) Copyright © 2025, Oracle and/or its affiliates 17 2.

    テーブルにデータを⼊れる INSERT INTO gps_points (route_id, timestamp, geom) VALUES (1, '2025-08-08 19:32:19', ST_GeomFromText('POINT(33.593207 130.401885)', 4326)), (1, '2025-08-08 19:33:09', ST_GeomFromText('POINT(33.593298 130.401940)', 4326)), (1, '2025-08-08 19:34:13', ST_GeomFromText('POINT(33.593188 130.401588)', 4326)), (1, '2025-08-08 19:35:13', ST_GeomFromText('POINT(33.592957 130.401008)', 4326)), (1, '2025-08-08 19:37:15', ST_GeomFromText('POINT(33.592464 130.399689)', 4326)), (1, '2025-08-08 19:38:10', ST_GeomFromText('POINT(33.592308 130.398995)', 4326)), (1, '2025-08-08 19:39:16', ST_GeomFromText('POINT(33.592100 130.398521)', 4326)), (1, '2025-08-08 19:40:13', ST_GeomFromText('POINT(33.592054 130.397843)', 4326)), (1, '2025-08-08 19:41:12', ST_GeomFromText('POINT(33.591939 130.397202)', 4326)), (1, '2025-08-08 19:42:18', ST_GeomFromText('POINT(33.591484 130.396461)', 4326)), (1, '2025-08-08 19:43:12', ST_GeomFromText('POINT(33.591304 130.395793)', 4326)), (1, '2025-08-08 19:44:14', ST_GeomFromText('POINT(33.590714 130.395762)', 4326)), (1, '2025-08-08 19:45:00', ST_GeomFromText('POINT(33.590549 130.396011)', 4326)), (1, '2025-08-08 19:46:35', ST_GeomFromText('POINT(33.590462 130.395970)', 4326)), (1, '2025-08-08 19:47:17', ST_GeomFromText('POINT(33.590226 130.396063)', 4326));
  10. 実⾏例) Copyright © 2025, Oracle and/or its affiliates 18 3.

    Spatial関数を使って、GPSのポイントデータを軌跡データに変換する mysql> SELECT ST_ASTEXT(CAST(ST_Collect(geom) AS LINESTRING)) FROM -> (SELECT route_id, -> timestamp, -> geom, -> ROW_NUMBER() OVER (PARTITION BY route_id ORDER BY timestamp) -> FROM gps_points) AS sorted_points -> GROUP BY route_id¥G *************************** 1. row *************************** ST_ASTEXT(CAST(ST_Collect(geom) AS linestring)): LINESTRING( 33.593207 130.401885,33.593298 130.40194,33.593188 130.401588,33.592957 130.401008, 33.592464 130.399689,33.592308 130.398995,33.5921 130.398521,33.592054 130.397843, 33.591939 130.397202,33.591484 130.396461,33.591304 130.395793,33.590714 130.395762, 33.590549 130.396011,33.590462 130.39597,33.590226 130.396063) 1 row in set (0.00 sec) route_id毎にデータを時刻順にソート ※ST_Collect関数︓単⼀のジオメトリ値を集合に変換する関数、この例ではPOINT型のデータをMULTIPOINT型に変換している ※CAST関数︓データ型を変換する関数、この例ではMULTIPOINT型のデータをLINESTRING型に変換している ※ST_ASTEXT関数︓ジオメトリデータをテキストデータに変換する関数
  11. 例) Copyright © 2025, Oracle and/or its affiliates 20 4.

    変換したデータを別のテーブルに格納 CREATE TABLE gps_line ( id INT AUTO_INCREMENT PRIMARY KEY, route_id INT NOT NULL, -- ルート識別⼦ geom LINESTRING NOT NULL SRID 4326 -- GPSポイントを軌跡に変換した値を格納 ); INSERT INTO gps_line(route_id, geom) SELECT route_id, CAST(ST_Collect(geom) AS LINESTRING) FROM (SELECT route_id, timestamp, geom, ROW_NUMBER() OVER (PARTITION BY route_id ORDER BY timestamp) FROM gps_points) AS sorted_points GROUP BY route_id; ※LINESTRING型のデータをテーブルにINSERTするため、2ページ前の実⾏例で使っていたST_ASTEXT関数は不要
  12. 昨⽇の19時32分から19時47分までの移動データ ※約1分間隔のデータであるため、少し荒いです Copyright © 2025, Oracle and/or its affiliates 25

    サンプルデータ INSERT INTO gps_points (route_id, timestamp, geom) VALUES (1, '2025-08-08 19:32:19', ST_GeomFromText('POINT(33.593207 130.401885)', 4326)), (1, '2025-08-08 19:33:09', ST_GeomFromText('POINT(33.593298 130.401940)', 4326)), (1, '2025-08-08 19:34:13', ST_GeomFromText('POINT(33.593188 130.401588)', 4326)), (1, '2025-08-08 19:35:13', ST_GeomFromText('POINT(33.592957 130.401008)', 4326)), (1, '2025-08-08 19:37:15', ST_GeomFromText('POINT(33.592464 130.399689)', 4326)), (1, '2025-08-08 19:38:10', ST_GeomFromText('POINT(33.592308 130.398995)', 4326)), (1, '2025-08-08 19:39:16', ST_GeomFromText('POINT(33.592100 130.398521)', 4326)), (1, '2025-08-08 19:40:13', ST_GeomFromText('POINT(33.592054 130.397843)', 4326)), (1, '2025-08-08 19:41:12', ST_GeomFromText('POINT(33.591939 130.397202)', 4326)), (1, '2025-08-08 19:42:18', ST_GeomFromText('POINT(33.591484 130.396461)', 4326)), (1, '2025-08-08 19:43:12', ST_GeomFromText('POINT(33.591304 130.395793)', 4326)), (1, '2025-08-08 19:44:14', ST_GeomFromText('POINT(33.590714 130.395762)', 4326)), (1, '2025-08-08 19:45:00', ST_GeomFromText('POINT(33.590549 130.396011)', 4326)), (1, '2025-08-08 19:46:35', ST_GeomFromText('POINT(33.590462 130.395970)', 4326)), (1, '2025-08-08 19:47:17', ST_GeomFromText('POINT(33.590226 130.396063)', 4326));
  13. Copyright © 2025, Oracle and/or its affiliates 27 昨⽇の移動ルート •

    エンジニアカフェ から ふとっぱら 天神総本店 へ移動
  14. • 2つの曲線の類似度を測るための数学的な⼿法 • MySQLではST_FrechetDistance関数でフレシェ距離を計算可能 Copyright © 2025, Oracle and/or its

    affiliates 30 フレシェ距離(Frechet distance) GPSデータの軌跡データへの変換と組み合わせれば、 特定のルートで移動したかどうかの判断などに使える
  15. 例) Copyright © 2025, Oracle and/or its affiliates 32 1.

    GPSデータを収集するテーブルを作成 CREATE TABLE walk_trajectories ( id INT AUTO_INCREMENT PRIMARY KEY, walker_name VARCHAR(100), trajectory LINESTRING NOT NULL SRID 4326 );
  16. 例) Copyright © 2025, Oracle and/or its affiliates 33 2.

    歩⾏者のGPSデータを軌跡データに変換してからテーブルに格納 INSERT INTO walk_trajectories (walker_name, trajectory) VALUES ('Red Walker', ST_GeomFromText('LINESTRING( 37.79562087383118 -122.46702694852982,<略>)', 4326)); INSERT INTO walk_trajectories (walker_name, trajectory) VALUES ('Orange Walker', ST_GeomFromText('LINESTRING( 37.79482108844495 -122.4645294833186,<略>)', 4326)); INSERT INTO walk_trajectories (walker_name, trajectory) VALUES ('Blue Walker', ST_GeomFromText('LINESTRING( 37.795951956800835 -122.46451100656672,<略>)', 4326)); INSERT INTO walk_trajectories (walker_name, trajectory) VALUES ('Green Walker', ST_GeomFromText('LINESTRING( 37.79479601418929 -122.46357793761146,<略>)', 4326));
  17. 例) Copyright © 2025, Oracle and/or its affiliates 34 3.

    特定のルートの軌跡データをテーブルに格納 INSERT INTO walk_trajectories (walker_name, trajectory) VALUES ('Sample Route', ST_GeomFromText('LINESTRING( 37.79360088412314 -122.46428847312926,37.79744139891328 -122.46510386466979, 37.79937853647067 -122.46860817074773)', 4326));
  18. 実⾏例) Copyright © 2025, Oracle and/or its affiliates 36 4.

    特定のルートと歩⾏者のルートの類似度を⽐較 mysql> SELECT walker_name, id, -> ST_FrechetDistance(trajectory, -> (SELECT trajectory -> FROM walk_trajectories -> WHERE walker_name='Sample Route')) as similarity -> FROM walk_trajectories -> ORDER BY similarity; +---------------+----+--------------------+ | walker_name | id | similarity | +---------------+----+--------------------+ | Sample Route | 5 | 0 | | Orange Walker | 2 | 241.65190882342154 | | Blue Walker | 3 | 261.68893003364565 | | Green Walker | 4 | 429.19109867209164 | | Red Walker | 1 | 453.59273618286403 | +---------------+----+--------------------+ 5 rows in set (0.00 sec)
  19. 実⾏例) Copyright © 2025, Oracle and/or its affiliates 38 重なりの多いルートから順番に表⽰

    mysql> SELECT t1.walker_name,t2.walker_name, -> ST_Length(ST_Intersection(t1.trajectory, t2.trajectory)) as common_length -> FROM walk_trajectories t1 -> CROSS JOIN walk_trajectories t2 ON t1.id < t2.id -> ORDER BY common_length DESC; +---------------+---------------+--------------------+ | walker_name | walker_name | common_length | +---------------+---------------+--------------------+ | Orange Walker | Blue Walker | 423.1932792589895 | | Orange Walker | Green Walker | 172.44142700478628 | | Red Walker | Orange Walker | 107.59951501720846 | | Blue Walker | Green Walker | 26.921615355894808 | | Red Walker | Blue Walker | 13.384680833787076 | | Red Walker | Green Walker | NULL | <略> | Green Walker | Sample Route | NULL | +---------------+---------------+--------------------+ 10 rows in set (0.00 sec)
  20. Ø MySQL 8.0で強化されたGIS機能と使⽤事例のご紹介+α https://speakerdeck.com/yoshiakiyamasaki/mysql-8-dot-0deqiang-hua-saretagisji-neng- toshi-yong-shi-li-falsegoshao-jie-a Ø MySQL 8.0 GIS機能チュートリアル https://speakerdeck.com/yoshiakiyamasaki/mysql-8-dot-0-gisji-neng-tiyutoriaru-6052f01e-

    445a-4f55-bcda-a0e3fad06332 Ø 周辺知識から理解するMySQL の GIS機能 〜ClubMySQL #4 ※坂井さん(OSGeo.JP 運営委員&⽇本MySQLユーザ会 副代表)の発表資料 https://www.slideshare.net/sakaik/mysql-gis-clubmysql-4 参考資料 Copyright © 2025, Oracle and/or its affiliates 42
  21. Ø MySQLで処理するGIS 〜地球が丸いことを覚えたMySQL〜 https://speakerdeck.com/yoshiakiyamasaki/mysql-gis-foss4g-tokai-2023 Ø FOSS4G HOKKAIDO 2019 でのハンズオン資料 Ø

    JavaScriptとMySQLでGISを作ってみよう https://foss4g.hokkaido.jp/archive/2019/ 参考資料 Copyright © 2025, Oracle and/or its affiliates 43
  22. MySQLサーバーは全て共通のソースコードのためハイブリッド構成も可能 MySQLを⾃社で運⽤管理 MySQL HeatWave • MySQLチームが100%開発・ 提供するクラウド・サービス • Amazon RDS

    (MySQL)の 1/3以下のコスト • データ損失なし、⾃動フェイルオー バーの⾼可⽤性機能をマネージ ドサービスで提供 MySQL Operator for k8s • MySQL サーバーをKubernetes上に 構築し運⽤管理 柔軟なMySQLの利⽤⽅法 47 オンプレミスでのMySQL • バージョン選択や構成を 最も柔軟に選択可能 IaaS上でのMySQL • OCIのマーケットプレイスの イメージから簡単に環境構築 商⽤版MySQL • コミュニティ版に加え、サポートや セキュリティに優れた商⽤版も MySQLのマネージドサービス クラウドネイティブなMySQL いずれの利⽤⽅法でもMySQL開発チームと連携した 専⾨部隊によるサポートサービスをご利⽤いただけます※ Copyright © 2025, Oracle and/or its affiliates MySQL :: MySQL Operator for Kubernetes テクニカルアップデート ※コミュニティ版を除く
  23. • 最⼤のMySQLのエンジニアリングおよびサポート組織 • MySQL開発チームによるサポート • 29⾔語で世界クラスのサポートを提供 • メンテナンス・リリース、バグ修正、パッチ、アップデートの提供 • 24時間x365⽇サポート

    • MySQL コンサルティング・サポート 開発チームと⼀体となったサポートサービス ⇒ 商⽤版MySQL サーバー及び MySQL HeatWave 利⽤者に提供 Oracle Premier Support for MySQL Copyright © 2025, Oracle and/or its affiliates 48 Get immediate help for any MySQL issue, plus expert advice
  24. MySQL コミュニティ Copyright © 2025, Oracle and/or its affiliates 50

    8/9/25 § MySQL コミュニティの紹介 § MySQL への貢献 § Oracle Contribution Agreement (OCA) § MySQL無償認証制度
  25. MySQL コミュニティの紹介 Copyright © 2025, Oracle and/or its affiliates 51

    • MySQL コミュニティへの貢献プロセスの運営 • MySQL ユーザーグループへの⽀援 https://dev.mysql.com/community/mug/ • 全世界でのサードパーティによるカンファレンスやイベントへの⽀援や参加 https://dev.mysql.com/community/ • 教育ビデオの作成 • MySQL 短編動画 (MySQL Shorts) • MySQL ⼊⾨編シリーズ (MySQL 101 for Biginners) • https://www.youtube.com/@mysql • MySQL RockStar プログラム • MySQLの利⽤促進に最も精⼒的に取り組んだ MySQL コミュニティ・メンバーへの表彰 • 第1回: https://blogs.oracle.com/mysql/post/mysql-rockstars-2022 • MySQL ACE プログラム • MySQL プロジェクトでの ACE プログラムの運営 • https://ace.oracle.com/pls/apex/ace_program/r/oracle-aces/home
  26. MySQL への貢献 • MySQL オープンソースプロジェクトのコントリビューターコミュニティへの参加: https://forums.oracle.com/ords/apexds/post/contributing-code-to-mysql-8037 • コントリビュータになるために持つべきこと • MySQL

    の機能を変更/修正したい、あるいは新しい機能を追加したいといった要望 • MySQL ソースコードのダウンロード http://dev.mysql.com/downloads/ • bugs.mysql.com のアカウント http://bugs.mysql.com or • 有効な GitHub アカウント https://github.com • Oracle Contribution Agreement (OCA) への署名 https://oca.opensource.oracle.com/ • OCAは、コントリビューターとオラクルの両⽅を法的攻撃から保護する短い法的契約です。OCAに署名することにより、コントリビュー ターはオラクルがコントリビューターのコードをオラクル・ソフトウェアで使⽤することが法的に許可されていること、およびコントリビューター の知る限りにおいて、そのコードに特許的な問題がないことに同意することになります。 Copyright © 2025, Oracle and/or its affiliates 52
  27. MySQL 無償認証制度 • MySQL コミュニティチームは、Oracle University および Oracle Academy と協⼒し、

    mylearn.oracle.com を介して、2ヶ⽉間の指定期間内に使⽤できる無料のトレーニングバウチャー/クレジッ トを受講者に提供します。 • ご興味のある⽅は、以下についての詳細をお知らせくだされば、MySQL コミュニティから連絡いたします。 • 名前 • 姓 • Email アドレス • 居住国 • https://education.oracle.com/ Copyright © 2025, Oracle and/or its affiliates 53
  28. 連絡先 • MySQL コミュニティとのコンタクト先⼀覧: • MySQL コミュニティページ, https://dev.mysql.com/community/ • MySQL

    Slack, https://mysqlcommunity.slack.com • The Oracle MySQL ブログ, https://blogs.oracle.com/mysql/ • The Oracle MySQL Japan ブログ, https://blogs.oracle.com/mysql-jp/ • Planet MySQL, https://planet.mysql.com/ • LinkedIn, https://www.linkedin.com/groups/60715/ • ブログ, https://lefred.be/ • MySQL フォーラム, http://lists.mysql.com/ • ディスカッションフォーラム, http://forums.mysql.com Copyright © 2025, Oracle and/or its affiliates 54