7

私が持っているのは(私が思うに)単純なSQLServer空間クエリです:

いくつかの4辺のポリゴン(つまり、Webページのグーグル/ビングマップのビューポート/バウンディングボックス)内に存在するすべての米国の州を取得します。

SELECT CAST(2 AS TINYINT) AS LocationType, a.Name AS FullName, 
    StateId, a.Name, Boundary.STAsText() AS Boundary, 
    CentrePoint.STAsText() AS CentrePoint
FROM [dbo].[States] a
WHERE @BoundingBox.STIntersects(a.Boundary) = 1

実行には6秒かかります:(

これが実行計画です。

削除

そして、フィルター操作の統計...

削除

さて、これをデバッグする方法がわかりません..微調整する必要があるものを理解するためなど。空間インデックスはありますか?そう信じる ...

/****** Object:  Index [SPATIAL_States_Boundary]    
        Script Date: 07/28/2010 18:03:17 ******/
CREATE SPATIAL INDEX [SPATIAL_States_Boundary] ON [dbo].[States] 
(
    [Boundary]
)USING  GEOGRAPHY_GRID 
WITH (
    GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH), 
    CELLS_PER_OBJECT = 1024, PAD_INDEX  = OFF, SORT_IN_TEMPDB = OFF, 
    DROP_EXISTING = OFF, ALLOW_ROW_LOCKS  = ON, 
    ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

GEOGRAPHY返されるデータについてさらに情報を提供する必要がありますか?例えば。ポイント数など?または、実行profilerしてそこからいくつかの統計を提供する必要がありますか?

または、Cells_per_object / Gridsが正しく設定されていません(これらの値をTBHに設定する必要があるかどうかは本当にわかりません)。

誰か助けてもらえますか?お願いします?

更新/編集:

以下の@Bobsからの最初の応答の後、主キー(クラスター化インデックス)が50の奇数行を持つテーブルの非クラスター化インデックスよりも高速であるため、空間インデックスが使用されていないことを確認しました...次に、強制的に空間インデックス(shits-n-giggles用):-

SELECT CAST(2 AS TINYINT) AS LocationType, a.Name AS FullName, 
    StateId, a.Name, Boundary.STAsText() AS Boundary, 
    CentrePoint.STAsText() AS CentrePoint
FROM [dbo].[States] a WITH (INDEX(SPATIAL_States_Boundary))
WHERE @BoundingBox.STIntersects(a.Boundary) = 1

...そして..クエリが即座に実行されるものを推測します。

WTF?他の誰かが理由を知っていますか?また、理由/内容を説明するために、そのクエリプランを投稿する必要がありますか?

4

2 に答える 2

7

クエリを実行するための最適な計画があるようです。そこを改善するのは難しいでしょう。ここにいくつかの観察があります。

クエリは、PK_States インデックスでクラスター化インデックス スキャンを実行しています。空間インデックスを使用していません。これは、クエリ オプティマイザーが、他のインデックスではなくクラスター化インデックスを使用する方が適切であると判断したためです。なんで?おそらく、States テーブルに行がほとんどないためです (50 に加えて、ワシントン、DC、プエルトリコなどの他のいくつかの行)。

SQL Server は、8KB ページでデータを格納および取得します。フィルター操作の行サイズ (「行サイズの見積もり」を参照) は 8052 バイトです。これは、1 ページあたり 1 行、テーブル全体で約 50 ページであることを意味します。クエリ プランは、これらの行のうち約 18 行を処理すると見積もっています (「見積行数」を参照)。これは、処理する重要な行数ではありません。私の説明は、表の一部である余分なページには対応していませんが、要点は、その数が 50,000 ページではなく約 50 であるということです。

SPATIAL_States_Boundry インデックスの代わりに PK_States インデックスを使用する理由に戻ります。クラスタ化インデックスには、定義上、テーブルの実際のデータが含まれています。非クラスター化インデックスは、データが存在するページを指しているため、取得するページがさらにあります。したがって、非クラスター化インデックスは、大量のデータがある場合にのみ役立ちます。

ページ プロセスの数を減らすためにできること (たとえば、カバリング インデックスを使用する) があるかもしれませんが、現在のクエリは既に十分に最適化されており、パフォーマンスの大幅な向上は見られません。

于 2010-07-28T21:11:43.063 に答える
2

インデックスヒントなしでこれを試してください:

EXEC sp_executesql N'
  SELECT CAST(2 AS TINYINT) AS LocationType, a.Name AS FullName, 
      StateId, a.Name, Boundary.STAsText() AS Boundary, 
      CentrePoint.STAsText() AS CentrePoint
  FROM [dbo].[States] a
  WHERE @BoundingBox.STIntersects(a.Boundary) = 1'
, N'@BoundingBox GEOGRAPHY', @BoundingBox

それで違いが生じる場合は、詳細についてはこちらをご覧ください。

SSMSでコードを実行している場合は、空間クエリの周囲でsp_executesqlを使用して(または、空間値をパラメーターとして使用する独自のストアドプロシージャを使用して)、クエリコスターがクエリプランの作成時にパラメーター値を「認識」していることを確認します。 、つまり、バッチの開始時、またはストアドプロシージャまたはsp_executesqlへのエントリ時。

于 2010-09-05T06:02:19.670 に答える