SQL Server 2012の近接検索の最速の戦略


8

これが私の最初の質問です。ご容赦ください。

私は、近くの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よりも遅くなるようです。

これについて共有する経験がある人はいますか?これに対するより良い/正しいアプローチはありますか?


本当にそれは「依存する」答えです。照会するデータの量は間違いなく要因です。SQL Server 2012を使用しているため、データベースクエリは非常に高速です。ただし、msdn.microsoft.com / en-us / library / ff929109.aspxのルールに従っていることを確認してください。そうしないと、空間インデックスは使用されません。
MickyT 2014年

@MickyT最近傍クエリは別の方法で最適化されていますか?半径内のすべてのポイントを取得するため、order by句もTOP句もありません。Lat、Long、およびGeometry列を使用してテストデータベースを作成し、400万レコードを追加しました。STDistanceを使用した空間インデックスベースの検索は瞬時に行われますが、境界ボックスを含むLatおよびLong列も非常に高速です。何十億ものポイントを追加して、一方が他方よりも優れているかどうかを確認します。そうでない場合は、空間インデックスを使用します。
Loudenvier 2014年

クエリが空間インデックスを使用しているようです。私はその特定のものについては多くのテストを行っていません。条件があることを読んだことを思い出してください。別のオプションとして、バウンディングボックス検索を実行する場合は、フィルターを試してください。 msdn.microsoft.com/en-us/library/cc645883.aspx
MickyT 2014年

データベースが空間のRツリーインデックスを実装する理由は、データベースがジオハッシュまたは個別のxインデックスとyインデックスの検索よりも高速であるためです。使い方はさまざまですが、ポイントしかないという理由だけで空間を使用するのは過剰ではありません。ジオメトリタイプを使用しても何も失うことはなく、潜在的には(速度の点だけでなく)多くを得ることができますが、将来の校正においては。バッファリングやポリゴン交差を後日追加したい場合はどうしますか?最終的には、知っている唯一の方法は、あなたのユースケースをテストすることですが、私の2cは、使用法1である
ジョン・パウエル

@JohnBarça50,000,000ポイントを追加するいくつかのテストを実行しました。クエリプランの計算後、空間インデックスを使用したクエリはほぼ瞬時に実行されますが、他のアプローチは完了するまで数秒かかります。さらにいくつかテストを行います。クエリは都市部で実行されるため、地域/近隣/地区/都市フィルターを追加します(場所は以前に逆ジオコーディングされています)。これにより、検索速度が向上する場合と向上しない場合があります。しかし、空間インデックスが50000000ポイントでこれを実行すると確信しているので、実際に必要な場合にのみ最適化を試みます。
Loudenvier 2014年

回答:


2

データベースが空間用のRツリーインデックスを実装する理由は、それらがジオハッシュまたは個別のxインデックスとyインデックスの検索よりも高速であるためです。ジオハッシュの問題は、近接タイプの検索を行うために、1つではなく9つの象限を検索する必要があることです。ジオハッシュの制限を参照してください。これらは、Rツリーを持たないデータベースで役立ち、2次元の範囲を持つオブジェクトを1次元で表現し、Bツリーでインデックスを付けることができます。xとyに別々の(または複合)インデックスを設定すると、関心領域でより多くのインデックスをゼロにスキャンする必要があるため、速度も低下しますが、Rツリーでは、インデックス検索は境界ボックスで行われます。

使い方はさまざまですが、ポイントしかないという理由だけで空間を使用するのは過剰ではありません。ジオメトリタイプを使用しても何も失うことはなく、潜在的には(速度の点だけでなく)多くを得ることができますが、将来の校正においては。バッファリングまたはポリゴン交差を後日追加したい場合はどうしますか?結局のところ、知る唯一の方法はユースケースをテストすることですが、私の2cは使用アプローチ1です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.