由于此查询中定义的提示,查询处理器无法生成查询计划.重新提交查询,而不使用SET FORCEPLAN

Mat*_*ius 8 sql-server indexing sql-server-2008 spatial-index sqlgeography

我正在运行以下:

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]))
Run Code Online (Sandbox Code Playgroud)

这个查询表现不佳,因为它不使用空间索引,所以我添加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]
Run Code Online (Sandbox Code Playgroud)

现在它给了我错误信息

消息8622,级别16,状态1,行15查询处理器由于此查询中定义的提示而无法生成查询计划.重新提交查询而不指定任何提示,也不使用SET FORCEPLAN.

我可以阅读并理解它告诉我删除提示,问题是为什么它在编译时成功但在运行时失败?我的索引有问题吗?

我需要更改SQL才能开始使用Spatial索引?

生成一些您可以在脚本后使用的数据.

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
Run Code Online (Sandbox Code Playgroud)

got*_*tqn 6

这里

最近邻查询必须满足以下要求才能使用空间索引:

  1. 其中一个空间列上必须存在空间索引,并且 STDistance() 方法必须在 WHERE 和 ORDER BY 子句中使用该列。
  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
Run Code Online (Sandbox Code Playgroud)

即使WITH INDEX删除了提示,您也可以检查它是否正在使用空间索引。

  • 我正在订购(只想要最近的 TOP x),但那里没有带有 STDistance() 的 where 子句;为我清除了它。谢啦。 (2认同)