MySQL 5.7で地理座標間の距離を計算する
MySQL 5.7で追加されたST_Distance_Sphere関数を使うと、2つの地理座標間の大圏距離を自前実装なしで計算できる。
MySQL 5.7で追加されたST_Distance_Sphere関数を使えば、Haversine公式を自前で実装しなくても2つの地理座標間の大圏距離を計算できます。
ST_Distance_Sphereの引数は経度、緯度の順で指定する必要があり、一般的な「緯度、経度」表記とは逆になります。この順序を逆にするとエラーは発生せず、誤った結果が返されるだけなので注意が必要です。
短距離の例
大阪市内の約2km離れた2地点間で、まずは短距離の挙動を見てみます。
SELECT ST_Distance_Sphere( GeomFromText('POINT(135.507260 34.693946)'), GeomFromText('POINT(135.526201 34.687316)') ) AS distance_meterFROM dual;| row | distance_meter |
|---|---|
| 1 | 1882.1360099034516 |

長距離の例
次は約400km離れたJR大阪駅とJR東京駅を使い、実測値として検証しやすい長距離での精度を確認します。
SELECT ST_Distance_Sphere( GeomFromText('POINT(135.495951 34.702488)'), -- JR Osaka station GeomFromText('POINT(139.767052 35.681168)') -- JR Tokyo station ) AS distance_meterFROM dual;| row | distance_meter |
|---|---|
| 1 | 403048.2752256764 |

極域に近い例
最後に、北極圏をはるかに超えたスヴァールバル諸島の2地点で、高緯度でも球面近似の精度が保たれるかを確かめます。
SELECT ST_Distance_Sphere( GeomFromText('POINT(16.379258 78.655621)'), -- Pyramiden Container Hostel GeomFromText('POINT(16.328528 78.655143)') -- Hotel Tulpan ) AS distance_meterFROM dual;| row | distance_meter |
|---|---|
| 1 | 1110.8932928975748 |

まとめ
3つの例を試した結果、ST_Distance_Sphereは2kmスケール、400kmスケール、そして単純な平面近似が最もずれやすい北緯78°付近のいずれでも正確な大圏距離を返してくれました。球面上の計算をこの関数がネイティブに処理してくれるので、「この2点はどれくらい離れているか」を求めるためだけにHaversineをアプリケーションコード側で実装したり、別のジオスペーシャルライブラリを用意したりする必要はありません。ただしGeomFromText('POINT(...)')は経度を緯度より先に指定する仕様なので、一般的な緯度・経度の順序に慣れていると引数を取り違えやすい点には注意してください。
Related posts
Gremlin で Amazon Neptune をクエリする
Gremlin によるグラフトラバーサルの例と、Neptune の読み取り・更新クエリにおけるトランザクション分離レベルの違い。
複数の Elasticsearch インデックスを横断して検索する
ワイルドカードパターンと明示的なカンマ区切りリストという 2 つの方法で、複数の Elasticsearch インデックスを一度にクエリする。
Cognito User PoolsとOIDCでSlackサインインを実装する
Cognito user poolをOIDC経由でSlackと連携させ、"Sign in with Slack"をAmplifyでNext.jsアプリに組み込みます。
Lambda Web AdapterでFastAPIをAWS Lambdaにデプロイする
Lambda Web Adapterを使うと、FastAPIで書いたAPIバックエンドをコンテナのまま単一のLambda関数にデプロイできます。
API Gateway WebSocket:モック統合の実装
バックエンドのLambdaを一切使わず、モック統合のみでAPI Gateway WebSocket APIを構築し、あらかじめ用意されたレスポンスを返します。
