7

我運行以下:由於此查詢中定義的提示,查詢處理器無法生成查詢計劃。請重新提交查詢,並且不使用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 [email protected]+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 

回答

3

here

以下要求必須滿足一個最近鄰查詢中使用空間索引:

  1. 空間索引必須存在於所述空間中的一個和STDistance()方法必須使用WHERE子句中的該列和BY子句中的ORDER 。
  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提示被移除空間索引。

+1

我正在訂購(只想要最近的TOP x),但沒有在那裏有STDistance()的where子句;爲我清理它。謝啦。 – radpin