これが私の最初の質問です。ご容赦ください。
私は、近くのPOI(ポイントosインタレスト)を見つけるために近接検索を行う必要があるモバイルアプリのバックエンドを実装しています。私はそれが非常に一般的なシナリオであり、非常にシンプルに見えることを知っていますが、実装できる方法はたくさんあるので、経験豊富な専門家がこれらの単純な空間検索をどのように実装しているかを確認したいと思います。
POIは単なるPOINTなので、交差点などを含む複雑な計算は必要ありません。そのため、最初に、GEOGRAPHY列と空間インデックスを使用すると、他の方法よりもやり過ぎになるか、遅くなる可能性があると考えました。だから私はそれを3つのアプローチに絞り込んだ:
1)GEOGRAPHYカラム+空間インデックス
これはおそらく、この問題の事実上の解決策です。空間インデックスと地理列があるので、それを使用して距離で検索できます。このようなもの。
SELECT * FROM POIs WHERE Loc.STDistance(@radius) <= @distance;
Locには空間インデックスがあるため、非常に高速です。
2)緯度と経度の列に「境界ボックス」を使用する
これは、空間インデックスを使用しない簡単なアプローチです。ポイントと半径の境界ボックスを見つけて、単にLatitude列とLongitude列を検索します。両方にインデックスが付けられている場合、この検索は非常に高速になります。距離関数を適用して、「円」の外側のいくつかの値をフィルタリングする必要がありますが、バウンディングボックスを通過しません。しかし、それはかなり速いはずです。このアイデアはここでよりよく説明されています:http : //www.movable-type.co.uk/scripts/latlong-db.html
このようなもの:
DECLARE @lat float
DECLARE @lon float
SET @lat = -23.001029
SET @lon = -43.328422
DECLARE @maxLat float, @minLat float, @maxlon float, @minLon float
DECLARE @R float
DECLARE @distance FLOAT = 100 -- A distance in meters
SET @R = 6378137 -- Earth
SET @maxLat = @lat + DEGREES(@distance/@R)
SET @minLat = @lat - DEGREES(@distance/@R)
SET @maxLon = @lon + DEGREES((@distance/@R/COS(RADIANS(@lat))))
SET @minLon = @lon - DEGREES((@distance/@R/COS(RADIANS(@lat))))
SELECT * from POIs
WHERE
Lat Between @minLat And @maxLat
And Lng Between @minLon And @maxLon
3)インデックス付きの列に格納された積分GEOHASHを使用します
このアプローチは非常に興味深いものであり、近接検索を行うためにREDIS順序付けセットと一緒に使用されているものです。原則は、積分GEOHASHを格納するインデックス付きの列を使用してSQL Serverに置き換えることができます。
私はArdbからこのアイデアを持っています:https : //github.com/yinqiwen/ardb/wiki/Spatial-Index
ここでも少しわかりやすい方法で説明されています:近接検索にgeohashを使用していますか?
言い換えれば、希望する検索の半径に対応するビット深度でGEOHASHを計算し、次に8つの近傍ジオハッシュを計算し、最後にこれらのジオハッシュをインデックス付き列の境界ボックスとして使用して検索を送信します。これは、SQLのWHERE句の9 BETWEEN演算子になります...誤ったPOIが返されるため、結果を除外する必要があります。
ただし、where句は2つではなく1つの列に対してのみクエリを実行しますが、where句はより複雑になるため、これは方法2よりも遅くなるようです。
これについて共有する経験がある人はいますか?これに対するより良い/正しいアプローチはありますか?