4

地理データ型として格納されているいくつかのエリア (ポリゴン) を含むテーブル (Table2) があります。テーブルには 1529 行が含まれます。別のテーブル (Table1) には、約があります。22000 行。それぞれに X/Y があり、そこからポイントを作成し、Geography 列に格納します。

各ポイントがどの領域に属しているかを調べるために、空間結合を行う必要があります。両方のテーブルに空間インデックスを作成しましたが、クエリが遅すぎると思います。現在、次のような結合を行うのに約 72 秒かかります。

SELECT ...
FROM [DatabaseA].dbo.Table1 t1 
INNER JOIN [DatabaseB].dbo.Table2 t2 ON t1.Geo.STIntersects(t2.Geo) = 1
WHERE t2.ObjectTypeId = 1 AND t2.CompanyId = 3

2 つのテーブルは異なるデータベースにありますが、同じサーバー上にあることに注意してください。

空間インデックスを作成する前は、クエリが非常に遅く、インデックスが使用されていることがわかります。ただし、table2 にインデックスを作成してもパフォーマンスには影響しません。table1 にインデックスを作成するだけでパフォーマンスが向上します。両方のインデックスに高レベルのグリッドがあります

実行計画を見ると、71% の時間を費やしている Filter 部分に気付きました。

CASE WHEN [Expr1015]>(2) THEN CASE WHEN [Expr1016]=[Expr1017] THEN (1) ELSE (0) END ELSE [DatabaseA].[dbo].[Table1].[Geo] as [t].[Geo].STIntersects([DatabaseB].[dbo].[Table2].[Geo] as [g].[Geo]) END=(1)

だから、私の質問は:

このクエリにそれほど時間がかかる必要がありますか? 他のグリッド サイズを使用する必要がありますか? そのフィルター式は何を意味するのでしょうか?

これを最適化するためのヒントはありますか?

4

2 に答える 2

2

同様の問題がありました。2000 ポイントと 85000 ポリゴンがありました。ポイントを一致するポリゴンと一致させる必要がありました。もともと、そのクエリには 8 時間かかっていました。

SELECT Item.Name, Polygons.Name
FROM dbo.Geofence AS Polygons 
JOIN dbo.ItemLocation AS Points 
ON Polygons.GeoFence.STIntersects(Points.GeoLocation) = 1

問題は、ポイント テーブルにクラスター化されていないインデックスがあることでした。クラスター化インデックスを追加すると、時間が 12 秒に短縮されました。

空間インデックス (以下のコード) を追加すると、時間が 1 秒に短縮されました。また、ポイント表に1つ追加しました。

CREATE SPATIAL INDEX [SpatialIndex-Polygons] ON dbo.Polygons
(
    [Geofence]
)USING  GEOGRAPHY_GRID 
WITH (GRIDS =(LEVEL_1 = MEDIUM,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = MEDIUM), 
CELLS_PER_OBJECT = 16, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
于 2016-03-23T20:30:09.547 に答える
1

つまり、パラメーター t2.Geo を使用して関数を呼び出しています。これは、t2.ObjecttypeId = 1 および t2.CompanyId = 3 である t2 のすべての値に対して関数によって評価する必要があります。テーブル t2 にインデックスを作成しても、'これらの事前計算されたインデックス値を使用できないため、本当に役に立ちません。代わりに、最初に関数 t1.Geo.STIntersects(t2.Geo) を t2 のすべての値に対して実行する必要があります。これらの値は、事前に計算されたインデックス値と実質的に関係がありません。

速度が目標であり、ストレージがある場合は、事前計算された t1.Geo.STIntersects(t2.Geo) のすべての組み合わせの結果を持つ 3 番目のテーブルを作成できます。次に、t1 と t2 を 3 番目のテーブルの事前計算された値に結合すると、ほぼ瞬時にクエリ結果を生成できるはずです (1,529 レコードと 22,000 レコードのソース テーブルの場合)。

t1 と t2 のデータが比較的静的な場合は、3 番目のテーブルのデータを更新するクエリを手動で再実行できます。頻繁に変更される場合は、t1 および t2 に対する更新、挿入、および削除のトリガーを介して自動的に維持するか、事前計算されたテーブルを更新するストアド プロシージャに更新、挿入、および削除をラップすることができます。

于 2012-08-30T17:44:46.430 に答える