2016-12-23 17 views
5

Mam kwerendy wydajność najbliższe sklepy:SQL Server: Geografia wydajność wyszukiwania - zapytania Najbliższe sklepy

Mamy tabelę, która zawiera około 50.000 rekordów (sklepy/punkt miejscach sprzedaży) w jednym kraju.

Każdy rekord zawiera location kolumny typu „geografii”

[LOCATION_geo] [geography] 

również dla wydajności utworzonego przestrzennego wskaźnika w tej kolumnie lokalizacji przy użyciu tej składni

CREATE SPATIAL INDEX [LOCATION_geoIndex] 
ON [dbo].[StoreLocations] ([LOCATION_geo]) 
USING GEOGRAPHY_GRID 
WITH (
GRIDS =(LEVEL_1 = MEDIUM,LEVEL_2 = MEDIUM,LEVEL_3 = MEDIUM,LEVEL_4 = MEDIUM), 
CELLS_PER_OBJECT = 16, PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

Mam procedurę przechowywaną, aby powrócić najbliższy 1000 sklepów dla aktualnej lokalizacji użytkownika.

USE [CompanyDB] 
GO 
SET STATISTICS TIME ON; 
GO 
declare @point geography; 
    set @point = geography::Point(49.2471855, -123.1078987, 4326); 

    SELECT top (1000) [id] 
      ,[Location_Name] 
      ,[LOCATION_geo]from [MYDB].[dbo].[StoreLocations] 
     where [LOCATION_geo].STDistance(@point) <= 10000 
     ORDER BY [LOCATION_geo].STDistance(@point) 

Problem polega na tym, że zapytanie zawsze trwa od 656 ms do 800 ms. I nie jest to akceptowalna wydajność dla naszej strony internetowej, ponieważ oczekujemy zbyt wielu połączeń synchronicznych.

(1000 row (s) affected)

SQL Server Execution Times: CPU time = 923 ms, czas, jaki upłynął = 1511 ms.

Uwaga: większość sklepów znajduje się w niektórych miastach (około 10 miast).

Zauważyłem także, że indeks klastrowy Uzyskaj koszt> = 45% całkowitego kosztu zapytania.

Moje pytanie brzmi: czy istnieje lepszy sposób na poprawę wydajności tego zapytania?

+0

Czy zastosowano indeks przestrzenny? Czy możesz potwierdzić, że jest używany przez plan wykonania? – gotqn

+0

Tak, jest używany, kosztuje 8%, a szacowany rozmiar rzędu 17 B, uporządkowany: prawda, szacowana liczba wykroczeń 109,8. –

+0

Również ten indeks w planie wykluczania zawsze zawiera ostrzeżenie "Kolumny bez statystyk: .... SRID, ....pk0 ", Właściwie to nie wiem co to znaczy –

Odpowiedz

1

Proponuję dodać jeszcze jedną kolumnę o nazwie odległość do tabeli, gdzie odległość będzie odległością LOCATION_geo od punktu (0, 0, 0). Zobacz przykładową instrukcję wstawiania poniżej:

INSERT INTO [GWDB].[dbo].[StoreLocations] 
      ([id] 
      ,[Location_Name] 
      ,[LOCATION_geo] 
      ,[Distance]) 
    Values(@id 
      ,@Location_Name 
      ,@LOCATION_geo 
      ,@LOCATION_geo..STDistance(Point(0, 0, 0)) 

Należy również utworzyć indeks na nowej odległości kolumny i zmienić swoje procedury przechowywanej, jak poniżej:

USE [CompanyDB] 
GO 
SET STATISTICS TIME ON; 
GO 
declare @point geography; 
declare @distance float; 
    set @point = geography::Point(49.2471855, -123.1078987, 4326); 
    set @distance = @point.STDistance(geography::Point(0, 0, 0); 

    SELECT top (1000) [id] 
      ,[Location_Name] 
      ,[LOCATION_geo]from [GWDB].[dbo].[StoreLocations] 
     where 
     distance < @distance AND 
     [LOCATION_geo].STDistance(@point) <= 10000 
     ORDER BY [LOCATION_geo].STDistance(@point) 
+0

Zasługuje na próbę. Ale nie spowoduje to dokładnego wyniku, myślę, że jeśli punkt wyszukiwania na zachodzie, to zapytanie otrzyma tylko tylko sklepy wschodnie (sklepy na wschód od punktu wyszukiwania). –

+0

Próbowałem, to nie poprawia wydajności naukowo, ponieważ myślę, że główną przyczyną niskiej wydajności jest zamówienie przez oświadczenie. Dziękuję. –

0

nie jestem pewien, jak dobrze będzie pracować w aplikacji, w niektórych przypadkach jest to szybsze, ale wolniejsze w innych. Gdy punkt, którego szukasz, znajduje się blisko Twoich danych, ten proces wyszukiwania jest szybszy. Gdy punkt wyszukiwania znajduje się dalej od danych, jest wolniejszy.

W moim scenariuszu wszystkie moje punkty są względnie bliskie (16 milionów rekordów). Są to różnice prędkości, które widzę.

|--Search Location--|--STIntersects() time--|--Numbers time--| 
-------------------------------------------------------------- 
|Close    |5 seconds    |700 ms   | 
|Far    |90 ms     |4 seconds  | 

Zasadniczo chodzi o stopniowe powiększanie obszaru wyszukiwania przy użyciu tabeli liczb.

DECLARE @point GEOGRAPHY = GEOGRAPHY::Point(49.2471855, -123.1078987, 4326) 
DECLARE @MaximumRaidus INT = 10000 

SELECT TOP 100 
    ID, 
    Location_Name, 
    Location_geo 
FROM 
    GWDB.dbo.StoreLocations WITH(INDEX([LOCATION_geoIndex])) 
CROSS JOIN 
    GWDB.dbo.Numbers N 
WHERE 
    N.n BETWEEN 0 AND SQRT(@MaximumRadius) 
    AND Location_geo.STIntersects(@Point.STBuffer(POWER(N.n,2))) = 1 
ORDER BY 
    N.n 
+0

Dziękuję, ale nie dostałem tego, co jest dbo. Tabela liczb? Nie mam takiego stołu. –

+0

@ Tarek_El-Mallah tabela liczb to po prostu tabela liczb całkowitych. To znaczy. Numery tabel mają jedną kolumnę (n INT), która ma wartości od 0 do 10000. Są bardzo przydatne do robienia rzeczy takich jak ta, do wypełniania luk w danych lub dzielenia danych na histogram, itp. Google termin i powinieneś znaleźć kilka odniesień do ich zastosowań i jak je tworzyć. – hcaelxxam

Powiązane problemy