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

Query processor could not produce a query plan because of the hints defined in this query. Resubmit the query and without using 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]

现在它给我错误信息

Msg 8622, Level 16, State 1, Line 15 Query processor could not produce a query plan because of the hints defined in this query. Resubmit the query without specifying any hints and without using 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

来自here

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

  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 returns 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 提示,您也可以检查它是否正在使用空间索引。

在我的例子中,我将数据库从一个数据库移动到另一个数据库,但我忘记了数据库索引迁移。

在新数据库中创建索引并解决问题