11

いくつかの空間検索機能をPostGISを使用したPostgresからSQLServerに移行する作業を行っていますが、インデックスを使用した場合でも、かなりひどいパフォーマンスが見られます。

私のデータは約100万ポイントであり、それらのポイントのどれが特定の形状内にあるかを知りたいので、クエリは次のようになります。

DECLARE @Shape GEOMETRY = ...
SELECT * FROM PointsTable WHERE Point.STWithin(@Shape) = 1

かなり小さい形状を選択すると、1秒未満の時間が得られる場合がありますが、形状がかなり大きい場合(場合によってはそうです)、5分を超える時間が得られます。Postgresで同じ検索を実行すると、常に1秒未満になります(実際、ほとんどすべてが200ミリ秒未満です)。

インデックスでいくつかの異なるグリッドサイズ(すべて高、すべて中、すべて低)、オブジェクトごとに異なるセル(16、64、256)を試しましたが、何をしても時間はかなり一定に保たれます。もっと組み合わせてみたいのですが、どういう方向に行けばいいのかわからないです。オブジェクトごとにより多くのセル?以下?グリッドサイズの奇妙な組み合わせ?

私は自分のクエリプランを調べましたが、それらは常にインデックスを使用していますが、まったく役に立たないだけです。インデックスなしで試してみましたが、それほど悪くはありません。

これについて誰かがアドバイスできることはありますか?私が見つけたものはすべて、「インデックスに関するアドバイスを提供することはできません。すべてを試してみればうまくいくかもしれません」と示唆していますが、インデックスの作成には10分かかるため、これを盲目的に行うのは時間の無駄です。

編集:私はこれをMicrosoftフォーラムにも投稿しました。ここに彼らがそこで求めたいくつかの情報があります:

私が得ることができた最高の実用的なインデックスはこれでした:

CREATE SPATIAL INDEX MapTesting_Location_Medium_Medium_Medium_Medium_16_NDX
    ON MapTesting (Location)
 USING GEOMETRY_GRID
  WITH (
    BOUNDING_BOX = ( -- The extent of our data, data is clustered in cities, but this is about as small as the index can be without missing thousands of points
        XMIN = -12135832,
        YMIN = 4433884,
        XMAX = -11296439,
        YMAX = 5443645),
    GRIDS = (
        LEVEL_1 = MEDIUM,
        LEVEL_2 = MEDIUM,
        LEVEL_3 = MEDIUM,
        LEVEL_4 = MEDIUM),
     CELLS_PER_OBJECT = 256 -- This was set to 16 but it was much slower
  )

インデックスを使用する際に問題が発生しましたが、これは異なります。

これらのテストでは、インデックスごとにWITH(INDEX(...))句を使用してテスト検索(元の投稿にリストされているもの)を実行しました(グリッドサイズとオブジェクトごとのセルのさまざまな設定をテストします)。ヒント。また、各インデックスと同じ検索形状を使用してsp_help_spatial_geometry_indexを実行しました。上記のインデックスは最も速く実行され、sp_help_spatial_geometry_indexで最も効率的であるとリストされました。

検索を実行すると、次の統計が得られます。

(1 row(s) affected)
Table 'MapTesting'. Scan count 0, logical reads 361142, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'extended_index_592590491_384009'. Scan count 1827, logical reads 8041, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 6735 ms,  elapsed time = 13499 ms.

また、ランダムポイントをデータとして使用してみましたが(実際のデータを提供できないため)、この検索はランダムデータを使用すると非常に高速であることがわかりました。これにより、私たちの問題はグリッドシステムがデータをどのように処理するかであると私たちは信じるようになりました。

私たちのデータは州全体のアドレスであるため、非常に高密度の領域がいくつかありますが、ほとんどの場合、データはまばらです。問題は、グリッドサイズの設定が両方でうまく機能しないことだと思います。グリッドをに設定するHIGHと、インデックスは低密度領域で返されるセルが多すぎます。グリッドをに設定するLOWと、グリッドは高密度領域では役に立ちません(でMEDIUM、それほど悪くはありませんが、どちらも得意ではありません)。

インデックスを使用することができますが、役に立たないだけです。すべてのテストは「実際の実行プランの表示」をオンにして実行され、常にインデックスが表示されます。

4

8 に答える 8

5

私はちょうどその日を同様の問題に費やしました。特に、ポリゴンのセットは比較的小さいが、各ポリゴンは大きくて複雑な、ポイント イン ポリゴン タイプのクエリを実行しています。

ポリゴン テーブルの空間インデックスの場合、解決策は次のようになります。

  1. 古い MMLL などの代わりに「ジオメトリ オート グリッド」を使用します。と...
  2. 「オブジェクトあたりのセル数」を 2000 または 4000 に設定します (デフォルトが 16 であるため、簡単に推測できません!)

これは大きな違いをもたらしました。デフォルト構成の空間インデックスよりも 10 倍高速であり、インデックスがまったくない場合よりも 60 倍高速でした。

于 2013-05-17T04:23:04.777 に答える
3

SQL-Server の空間拡張と、インデックスが効率的に使用されるようにする方法について、いくつかの注意事項を次に示します。

どうやら、プランナーは、解析時に実際のジオメトリを知らなければ、適切なプランを作成するのが困難です。著者は挿入することを提案していexec sp_executesqlます:

交換:

-- does not use the spatial index without a hint
declare @latlonPoint geometry = geometry::Parse('POINT (45.518066 -122.767464)')
select a.id, a.shape.STAsText() 
from zipcodes a 
where a.shape.STIntersects(@latlonPoint)=1
go

と:

-- this does use the spatial index without using a hint
declare @latlonPoint geometry = geometry::Parse('POINT (45.518066 -122.767464)')
exec sp_executesql 
N'select a.id, a.shape.STAsText() 
from zipcodes a 
where a.shape.STIntersects(@latlonPoint)=1', N'@latlonPoint geometry', @latlonPoint
go
于 2010-08-12T17:15:42.370 に答える
2

STIntersectsは、インデックスを使用するために最適化されていると思います。特に、より大きな形状の場合、STWithinよりもパフォーマンスが向上します。

于 2010-08-26T17:31:48.847 に答える
2

PostGIS はR ツリー インデックスを使用するのに対し、 SQL サーバーはQuadtree インデックスを使用しますが、実装効率の問題は別として。

R ツリーは、ほとんどの場合、特にさまざまなジオメトリ サイズを持つ大規模なデータセットの場合に適したアルゴリズムです。

于 2014-06-23T08:44:22.377 に答える
2

私の直観的な反応は、「Microsoft は、エンタープライズ機能ではないため、わざわざ高速化しようとしなかったからです」です。多分私はシニカルです。

Postgres から移行する理由もわかりません。

于 2010-08-12T17:20:56.587 に答える
1

2 つのパスに分割してみてください。

  1. 候補を選択して一時テーブルに入れます.Filter()
  2. クエリ候補 w/ .STWithin().

例えば:

SELECT * INTO #this FROM PointsTable WHERE Point.Filter(@Shape) = 1
SELECT * FROM #this WHERE Point.STWithin(@Shape) = 1

SELECT *( I/O を削減するために必要な実際の列のみに置き換えます)

この種のマイクロ最適化は必要ないはずですが、以前にまともなパフォーマンスの改善を見たことがあります。また、(1) と (2) の比率によって、インデックスがどの程度選択的であるかを判断することができます。

于 2010-08-28T04:11:56.490 に答える
1

空間インデックスを正しく設定しましたか? バウンディングボックスは正しいですか?すべてのポイントは内側ですか?あなたの場合、おそらくGRIDSのHHMMが最適に機能します(バウディングボックスにもよります)。

sp_help_spatial_geometry_index を使用して何が問題なのかを確認できますか? http://msdn.microsoft.com/en-us/library/cc627426.aspx

代わりにフィルター操作を使用してみて、得られるパフォーマンスの数値を教えてください。(二次フィルター (真の空間演算) を経由せずに、一次フィルター (使用インデックス) のみを実行します)

セットアップに問題があります。Spatial は確かに新しい機能ですが、それほど悪くはありません。

于 2010-08-26T16:58:01.227 に答える
0

空間クエリには詳しくありませんが、パラメーター化されたクエリの問題である可能性があります

固定値で (パラメータを使用せずに) クエリを作成してみてください (パラメータ化されたクエリではパフォーマンスが低下する値を使用してください)、それを実行してください。時間をパラメーター化されたバージョンと比較します。はるかに高速な場合、問題はパラメーター化されたクエリです。

上記がはるかに高速な場合は、文字列に埋め込まれたパラメーター値を使用して SQL 文字列を動的に作成します。これにより、パラメーターを問題の原因から削除できます。

于 2010-08-23T06:58:10.023 に答える