7

Używam następujący:Procesor kwerend nie może utworzyć planu kwerend z powodu wskazówek zdefiniowanych w tym kwerendzie. Ponownie przesłać zapytanie i bez użycia 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])) 

tej kwerendy wykonywane źle, ponieważ nie używa indeksu przestrzenną, więc dodałem with(index([SpatialIndex_1])) na siłę.

Indeks geografia wygląda następujące:

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] 

Teraz to daje mi komunikat o błędzie

Msg 8622, Level 16, State 1, Linia procesor 15 zapytań nie mógł stworzenie planu zapytania z powodu wskazówki zdefiniowane w tym zapytaniu. Ponownie wprowadź zapytanie bez podawania jakichkolwiek wskazówek i bez użycia SET FORBULAN.

Czytam i rozumiem, że mówi mi, aby usunąć podpowiedź, pytanie brzmi, dlaczego udaje się kompilacji, ale kończy się niepowodzeniem w czasie wykonywania? Czy coś jest nie tak z moim indeksem?

Co muszę zmienić w SQL, aby rozpocząć korzystanie z indeksu Spatial?

wygenerować niektóre dane, które można użyć następującego skryptu.

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 

Odpowiedz

3

Od here:

następujące wymagania muszą być spełnione do najbliższego zapytania sąsiad wykorzystać indeks przestrzenny:

  1. przestrzennej indeksu musi być obecny na jednej z kolumn przestrzennych i Metoda STDistance() musi używać tej kolumny w klauzulach WHERE i ORDER BY.
  2. Klauzula TOP nie może zawierać instrukcji PERCENT.
  3. Klauzula WHERE musi zawierać metodę STDistance().
  4. Jeśli istnieje wiele predykatów w klauzuli WHERE, to predykat zawierający metodę STDistance() musi być połączony przez AND IN (INNT) z innym predykatem. Metoda STDistance() nie może być w opcjonalnej części klauzuli WHERE.
  5. Pierwsze wyrażenie w klauzuli ORDER BY musi używać metody STDistance() .
  6. Porządek sortowania pierwszego wyrażenia STDistance() w klauzuli ORDER BY musi być ASC.
  7. Wszystkie wiersze, dla których STDistance zwraca wartość NULL, muszą zostać odfiltrowane.

Tak, to powinno działać:

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 

Można sprawdzić, że jest to za pomocą indeksu przestrzenną nawet wskazówkę WITH INDEX jest usuwany.

+1

Zamawiam (po prostu chciałem najbliższego TOP x), ale nie miałem tam klauzuli where z STDistance(); wyjaśnili to dla mnie. Dzięki. – radpin