2016-05-04 9 views
0

は今、私は億のインサートのテーブルがあります:私のバックエンドで最大緯度 - - マックス経度緯度からのX距離のためのSQL

CREATE TABLE o (
    id   int UNIQUE, 
    latitude FLOAT(10, 8), 
    longitude FLOAT(11, 8) 

); 

を私は緯度/長いユーザーを受け付けておりますそれからx距離以内にすべてを返そうとしています。

1つの結果ごとに距離計算式を実行するのではなく、X距離の最大緯度/経度を計算できると考えていました。

私たちは、最大緯度/最小緯度、最大/最小緯度を見つけることで正方形を作成しています。

これらの最大値を取得すると、この範囲の値に対してクエリを実行し、サブセットを大幅に小さくして実際の距離式をオンにします(つまり、X距離内の値を見つける)。

あなたに私の質問は: 私はより速く走りますか?セットを取得するために

オプション1)

  • 億のエントリの距離式。

オプション2)

  • の代わりに、我々は緯度/長い最小/最大を計算億のエントリのセットに距離式を行います。
  • 1億エントリのテーブルからその範囲の値を選択してください
  • 私たちの新しい小さなセットでは、距離の公式を行います。

オプション3)オプション2は、より速く次の問題が実際にその数学の問題を解決されている場合

  • 何かがSQL

で、このために既に存在しています。

あなたが読書を続けることを見たい場合:

緯度/経度の距離の式

dlon = lon2 - lon1 
dlat = lat2 - lat1 
a = (sin(dlat/2))^2 + cos(lat1) * cos(lat2) * (sin(dlon/2))^2 
c = 2 * atan2(sqrt(a), sqrt(1-a)) 
d = R * c 

D(1マイルを想定)、及びRは、(の半径であるため、明らかに我々はこれを並べ替えることができます地球は)設定値であるので、D/R = Cを得る。

問題は、C/2 = atan2(sqrt(a)、sqrt(1-a))をどのようにして計算するのだろうか?

+1

あなたは車輪を再発明しています。 mysqlの空間データ型と関数を見てください。 – e4c5

答えて

0

1 - 100M行は、スキャンしてテストするためにたくさんあります。しばらくしてもOKですが、やるのが遅すぎます。

2 - 擬似正方形のバウンディングボックスを使用して

WHERE latitude BETWEEN ... 
    AND longitude BETWEEN ... 

を行うことは良い最初のステップです。緯度の範囲は単純な定数倍のXです。経度範囲もまた、cos(latitude)で割ります。

しかし、正方形内の行だけを検索しようとすると問題が発生します。インデックスをlatitudeおよび/またはlongitudeに個別にまたは一緒に組み合わせると、部分的にフィルタリングされます。つまり、経度を無視して、緯度範囲内のすべてを渡したり、その逆になります。距離を確認するために、10万行に減らすかもしれません。それは100,000,000よりはるかに優れていますが、あなたが望むほど良くはありません。

3 - http://mysql.rjweb.org/doc.php/latlng正方形に近づくか、非常に近いですか?それは拡大縮小するように設計されています。私は100万ではなく3M行だけをテストしましたが、うまくいくはずです。

主なやり方は、緯度をパーティション化してから、経度をPRIMARY KEYの最初の列にして、InnoDBがパーティション内の近くの行をクラスタリングするようにすることです。 Xマイル(またはkm)内のすべての行を検索すると、100Kではなく、必要な行の約2倍の行が表示されます(大円距離を計算する)。一番近い100アイテムを見つけたい場合は、約400(4x)に触れることがあります。

SPATIALインデックスの場合、ST_Distance_Sphere()ST_MakeEnvelope()が追加された5.7.6にアップグレードすることをお勧めします。 (MakeEnvelopeは、あなた自身でPolygonを構築するよりもわずかに便利です - それは平らな地球シンドロームを持っています)

関連する問題