web-dev-qa-db-ja.com

このクエリで定義されたヒントのため、クエリプロセッサはクエリプランを作成できませんでした。 SET FORCEPLANを使用せずに、クエリを再送信します

私は以下を実行しています:

_DECLARE @g geography;
declare @point nvarchar(50)  =''
declare @i int =0,
        @lat decimal(8,6) =0.0,
        @long decimal(8,6) =0.0,
        @start datetime = getdate()
set @lat =(select (0.9 -Rand()*1.8)*100)
set @long =(select (0.9 -Rand()*1.8)*100)
set @point = (select 'POINT('+CONVERT(varchar(10), @lat)+ '  ' 
             +CONVERT(varchar(10), @long)+')')
SET @g = geography::STGeomFromText(@point, 4326);
SELECT TOP 1000
    @lat,
    @long,
        @g.STDistance(st.[coord]) AS [DistanceFromPoint (in meters)] 
    ,   st.[coord]
    ,   st.id
FROM    Temp st with(index([SpatialIndex_1]))
_

このクエリは空間インデックスを使用しないためパフォーマンスが低下したため、with(index([SpatialIndex_1]))を追加して強制しました。

地理インデックスは次のようになります。

_CREATE SPATIAL INDEX [SpatialIndex_1] ON [dbo].Temp
(
    [coord]
)USING  GEOGRAPHY_GRID 
WITH (GRIDS =(LEVEL_1 = LOW,LEVEL_2 = MEDIUM,LEVEL_3 = LOW,LEVEL_4 = LOW), 
CELLS_PER_OBJECT = 16, PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF,
ONLINE = OFF, ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 95) 
ON [PRIMARY]
_

今それは私にエラーメッセージを与えます

メッセージ8622、レベル16、状態1、行15クエリプロセッサは、このクエリで定義されたヒントのため、クエリプランを生成できませんでした。ヒントを指定せず、SET FORCEPLANを使用せずに、クエリを再送信してください。

ヒントを削除するように指示されていることを読んで理解できます。質問は、コンパイルでは成功するのに実行時に失敗するのはなぜですか?インデックスに何か問題がありますか?

SQLが空間インデックスの使用を開始するには何を変更する必要がありますか?

次のスクリプトを使用して、いくつかのデータを生成できます。

_CREATE TABLE dbo.Temp
    (
    Id int NOT NULL IDENTITY (1, 1),
    Coord geography NOT NULL
    )  ON [PRIMARY]
     TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE dbo.Temp ADD CONSTRAINT
    PK_Temp PRIMARY KEY CLUSTERED 
    (
    Id
    ) 
WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
      ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
ON [PRIMARY]
GO


declare @i int =0
declare @lat decimal(8,6) =0.0
declare @long decimal(8,6) =0.0
while (@i < 47000)
begin
   set @lat =(select (0.9 -Rand()*1.8)*100)
   set @long =(select (0.9 -Rand()*1.8)*100)
   insert into Temp
   select geography::Point(@lat, @long,4326)
   set @i =@i+1
end
go

CREATE SPATIAL INDEX [SpatialIndex_1] ON [dbo].Temp
(
    [coord]
)USING  GEOGRAPHY_GRID 
WITH (GRIDS =(LEVEL_1 = LOW,LEVEL_2 = MEDIUM,LEVEL_3 = LOW,LEVEL_4 = LOW), 
   CELLS_PER_OBJECT = 16, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
   SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
   ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 95) 
ON [PRIMARY]
GO
_
8

から ここ

空間インデックスを使用するには、最近傍クエリで次の要件を満たす必要があります。

  1. 空間インデックスは空間列の1つに存在する必要があり、STDistance()メソッドはWHERE句とORDERBY句でその列を使用する必要があります。
  2. TOP句にPERCENTステートメントを含めることはできません。
  3. WHERE句には、STDistance()メソッドが含まれている必要があります。
  4. WHERE句に複数の述語がある場合、STDistance()メソッドを含む述語は、AND接続詞によって他の述語に接続する必要があります。 STDistance()メソッドをWHERE句のオプション部分に含めることはできません。
  5. ORDER BY句の最初の式では、STDistance()メソッドを使用する必要があります。
  6. ORDER BY句の最初のSTDistance()式の並べ替え順序はASCである必要があります。
  7. STDistanceがNULLを返すすべての行を除外する必要があります。

したがって、これは機能するはずです。

DECLARE @g geography;
declare @point nvarchar(50)  =''
declare @i int =0,
        @lat decimal(8,6) =0.0,
        @long decimal(8,6) =0.0,
        @start datetime = getdate()
set @lat =(select (0.9 -Rand()*1.8)*100)
set @long =(select (0.9 -Rand()*1.8)*100)
set @point = (select 'POINT('+CONVERT(varchar(10), @lat)+ '  ' 
             +CONVERT(varchar(10), @long)+')')
SET @g = geography::STGeomFromText(@point, 4326);

SELECT TOP 1000
    @lat,
    @long,
        @g.STDistance(st.[coord]) AS [DistanceFromPoint (in meters)] 
    ,   st.[coord]
    ,   st.id
FROM    Temp st with(index([SpatialIndex_1]))
WHERE @g.STDistance(st.[coord])  IS NOT NULL
ORDER BY @g.STDistance(st.[coord]) asc

WITH INDEXヒントが削除されていても、空間インデックスを使用していることを確認できます。

4
gotqn