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

时间:2016-01-13 10:47:03

标签: sql-server sql-server-2008 indexing 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]))

此查询效果不佳,因为它不使用空间索引,因此我添加了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查询处理器不能   由于此查询中定义的提示,因此会生成查询计划。   重新提交查询,而不指定任何提示,也不使用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

2 个答案:

答案 0 :(得分:4)

来自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返回NULL的所有行。
  8. 所以,这应该有效:

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

答案 1 :(得分:0)

就我而言,我将数据库从一个数据库迁移到另一个数据库,却忘记了数据库索引迁移。

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