私は、扱っているデータ セットに対して適切な SQL Server 2008 空間インデックスのセットアップを選択しようとしています。
データセットは、地球全体の等高線を表すポリゴンです。テーブルには 106,000 行あり、ポリゴンはジオメトリ フィールドに格納されています。
私が抱えている問題は、多くのポリゴンが地球の大部分をカバーしていることです。これにより、プライマリ フィルターで多くの行を除外する空間インデックスを取得することが非常に難しくなっているようです。たとえば、次のクエリを見てください。
SELECT "ID","CODE","geom".STAsBinary() as "geom" FROM "dbo"."ContA"
WHERE "geom".Filter(
geometry::STGeomFromText('POLYGON ((-142.03193662573682 59.53396984952896,
-142.03193662573682 59.88928136451884,
-141.32743833481925 59.88928136451884,
-141.32743833481925 59.53396984952896,
-142.03193662573682 59.53396984952896))', 4326)
) = 1
これは、テーブル内の 2 つのポリゴンのみと交差する領域をクエリしています。選択した空間インデックス設定の組み合わせに関係なく、その Filter() は常に約 60,000 行を返します。
もちろん、Filter() を STIntersects() に置き換えると、必要な 2 つのポリゴンだけが返されますが、当然、はるかに時間がかかります (Filter() は 6 秒、STIntersects() は 12 秒)。
60,000 行で改善される可能性が高い空間インデックスのセットアップがあるかどうか、または私のデータセットが SQL Server の空間インデックスとうまく一致しないかどうかについて、誰かヒントを教えてもらえますか?
より詳しい情報:
示唆されたように、世界中の 4x4 グリッドを使用して、ポリゴンを分割しました。QGIS でそれを行う方法が見つからなかったので、それを行うための独自のクエリを作成しました。最初に 16 個のバウンディング ボックスを定義しました。最初のボックスは次のようになりました。
declare @box1 geometry = geometry::STGeomFromText('POLYGON ((
-180 90,
-90 90,
-90 45,
-180 45,
-180 90))', 4326)
次に、各境界ボックスを使用して、そのボックスと交差するポリゴンを選択して切り捨てました。
insert ContASplit
select CODE, geom.STIntersection(@box1), CODE_DESC from ContA
where geom.STIntersects(@box1) = 1
明らかに、4x4 グリッドの 16 個のバウンディング ボックスすべてに対してこれを行いました。最終結果は、約 107,000 行の新しいテーブルを作成したことです (これは、実際には多くの巨大なポリゴンがないことを確認しています)。
オブジェクトごとに 1024 セルの空間インデックスを追加し、レベルごとのセルには低、低、低、低を追加しました。
ただし、非常に奇妙なことに、分割されたポリゴンを含むこの新しいテーブルは、古いテーブルと同じように機能します。上記の .Filter を実行しても、最大60,000 行が返されます。私はこれをまったく理解していません。明らかに、空間インデックスが実際にどのように機能するかを理解していません。
逆説的に、.Filter() はまだ 60,000 行を返しますが、パフォーマンスは向上しています。.Filter() は 6 秒ではなく約 2 秒かかり、.STIntersects() は 12 秒ではなく 6 秒かかるようになりました。
ここで要求されているのは、インデックスの SQL の例です。
CREATE SPATIAL INDEX [contasplit_sidx] ON [dbo].[ContASplit]
(
[geom]
)USING GEOMETRY_GRID
WITH (
BOUNDING_BOX =(-90, -180, 90, 180),
GRIDS =(LEVEL_1 = LOW,LEVEL_2 = LOW,LEVEL_3 = LOW,LEVEL_4 = LOW),
CELLS_PER_OBJECT = 1024,
PAD_INDEX = OFF,
SORT_IN_TEMPDB = OFF,
DROP_EXISTING = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
覚えていますが、オブジェクトごとにグリッドとセルのさまざまな設定を試しましたが、毎回同じ結果が得られました。
sp_help_spatial_geometry_index を実行した結果は次のとおりです。これは、単一のポリゴンが地球の 1/16 以上を占めていない私の分割データセットです。
Base_Table_Rows 215138 Bounding_Box_xmin -90 Bounding_Box_ymin -180 Bounding_Box_xmax 90 Bounding_Box_ymax 180 Grid_Size_Level_1 64 Grid_Size_Level_2 64 Grid_Size_Level_3 64 Grid_Size_Level_4 64 Cells_Per_Object 16 Total_Primary_Index_Rows 378650 Total_Primary_Index_Pages 1129 Average_Number_Of_Index_Rows_Per_Base_Row 1 Total_Number_Of_ObjectCells_In_Level0_For_QuerySample 1 Total_Number_Of_ObjectCells_In_Level0_In_Index 60956 Total_Number_Of_ObjectCells_In_Level1_In_Index 361 Total_Number_Of_ObjectCells_In_Level2_In_Index 2935 Total_Number_Of_ObjectCells_In_Level3_In_Index 32420 Total_Number_Of_ObjectCells_In_Level4_In_Index 281978 Total_Number_Of_Interior_ObjectCells_In_Level2_In_Index 1 Total_Number_Of_Interior_ObjectCells_In_Level3_In_Index 49 Total_Number_Of_Interior_ObjectCells_In_Level4_In_Index4236 Total_Number_Of_Intersecting_ObjectCells_In_Level1_In_Index 29 Total_Number_Of_Intersecting_ObjectCells_In_Level2_In_Index 1294 Total_Number_Of_Intersecting_ObjectCells_In_Level3_In_Index 29680 Total_Number_Of_Intersecting_ObjectCells_In_Level4_In_Index 251517 Total_Number_Of_Border_ObjectCells_In_Level0_For_QuerySample 1 Total_Number_Of_Border_ObjectCells_In_Level0_In_Index 60956 Total_Number_Of_Border_ObjectCells_In_Level1_In_Index 332 Total_Number_Of_Border_ObjectCells_In_Level2_In_Index 1640 Total_Number_Of_Border_ObjectCells_In_Level3_In_Index 2691 Total_Number_Of_Border_ObjectCells_In_Level4_In_Index 26225 Interior_To_Total_Cells_Normalized_To_Leaf_Grid_Percentage 0.004852925 Intersecting_To_Total_Cells_Normalized_To_Leaf_Grid_Percentage 0.288147586 Border_To_Total_Cells_Normalized_To_Leaf_Grid_Percentage 99.70699949 Average_Cells_Per_Object_Normalized_To_Leaf_Grid 405.7282349 Average_Objects_PerLeaf_GridCell 0.002464704 Number_Of_SRIDs_Found 1 Width_Of_Cell_In_Level1 2.8125 Width_Of_Cell_In_Level2 0.043945313 Width_Of_Cell_In_Level3 0.000686646 Width_Of_Cell_In_Level4 1.07E-05 Height_Of_Cell_In_Level1 5.625 Height_Of_Cell_In_Level2 0.087890625 Height_Of_Cell_In_Level3 0.001373291 Height_Of_Cell_In_Level4 2.15E-05 Area_Of_Cell_In_Level1 1012.5 Area_Of_Cell_In_Level2 15.8203125 Area_Of_Cell_In_Level3 0.247192383 Area_Of_Cell_In_Level4 0.003862381 CellArea_To_BoundingBoxArea_Percentage_In_Level1 1.5625 CellArea_To_BoundingBoxArea_Percentage_In_Level2 0.024414063 CellArea_To_BoundingBoxArea_Percentage_In_Level3 0.00038147 CellArea_To_BoundingBoxArea_Percentage_In_Level4 5.96E-06 Number_Of_Rows_Selected_By_Primary_Filter 60956 Number_Of_Rows_Selected_By_Internal_Filter 0 Number_Of_Times_Secondary_Filter_Is_Called 60956 Number_Of_Rows_Output 2 Percentage_Of_Rows_NotSelected_By_Primary_Filter 71.66655821 Percentage_Of_Primary_Filter_Rows_Selected_By_Internal_Filter 0 Internal_Filter_Efficiency 0 Primary_Filter_Efficiency 0.003281055
「Base_Table_Rows 215138」はあまり意味がありません。テーブルには215,000ではなく107,000行があります
レンダリングすると、データセットは次のようになります:
(ソース: norman.cx )
さらなる研究:
このデータを使用したプライマリ フィルターのパフォーマンスの悪さに、私は引き続き戸惑っています。そこで、データがどのように分割されるかを正確に確認するためのテストを行いました。元の分割されていない機能を使用して、テーブルに「セル」列を追加しました。次に、16 のクエリを実行して、フィーチャが 4x4 グリッド内でいくつのセルにまたがっているかをカウントしました。そこで、各セルに対して次のようなクエリを実行しました。
declare @box1 geometry = geometry::STGeomFromText('POLYGON ((
-180 90,
-90 90,
-90 45,
-180 45,
-180 90))', 4326)
update ContA set cells = cells + 1 where
geom.STIntersects(@box1) = 1
次に、表の「セル」列を見ると、データ セット全体で、4x4 グリッド内の複数のセルと交差するフィーチャは 672 個しかありません。では、まったく文字通り、幅 200 マイルの小さな四角形を参照するクエリに対して、プライマリ フィルターが 60,000 個のフィーチャを返すことができるでしょうか。
この時点で、これらの機能に対する SQL Server のパフォーマンスよりも優れた独自のインデックス作成スキームを作成できるようです。