Tabela T_PIN
ma 300 000 pinów i T_POLYGON
36 000 wielokątów. T_PIN
ma ten indeks:
CREATE SPATIAL INDEX [T_PIN_COORD] ON [dbo].[T_PIN]
(
[Coord]
)USING GEOGRAPHY_GRID
WITH (GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH),
CELLS_PER_OBJECT = 128, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY];
T_POLYGON
ma:
CREATE SPATIAL INDEX [T_POLYGON_COORD] ON [dbo].[T_POLYGON]
(
[COORD]
)USING GEOGRAPHY_GRID
WITH (GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH),
CELLS_PER_OBJECT = 128, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY];
Wykonanie zapytania w celu znalezienia przecięcia T_PIN
i jego wykonanie T_POLYGON
zajmuje ponad 45 minut:
SELECT COUNT(*)
FROM T_PIN
INNER JOIN T_POLYGON
ON T_PIN.Coord.STIntersects(T_POLYGON.COORD) = 1;
Wynik to 4,438,318 wierszy.
Jak mogę przyspieszyć to zapytanie?
Odpowiedzi:
Po pierwsze, sprawdź, czy używany jest indeks przestrzenny, patrząc na plan wykonania zapytania i sprawdź, czy istnieje element Poszukiwany indeks klastrowany (przestrzenny).
Zakładając, że jest używany, możesz spróbować dodać dodatkowy / uproszczony filtr oparty na obwiedni z uproszczonymi wielokątami, aby sprawdzić najpierw. Mecze z tymi uproszczonymi wielokątami mogą być następnie przeprowadzane przez filtr główny, aby uzyskać ostateczne wyniki.
1) Dodaj nową kolumnę geografii i geometrii do tabeli [dbo]. [T_POLYGON]:
2) Utwórz wielokąty obwiedni (obejmuje to wstępną konwersję do geometrii, aby skorzystać z STEnvelope ()):
3) Utwórz indeks przestrzenny w uproszczonej kolumnie geograficznej
4) Uzyskaj skrzyżowania z tą uproszczoną kolumną geograficzną, a następnie ponownie przefiltruj według pasujących typów danych geograficznych. Z grubsza coś takiego:
EDYCJA : możesz zastąpić (1) i (2) tą wyliczoną, utrwaloną kolumną. podziękowania dla Paula White'a za sugestię.
źródło
Takie zapytania często zajmują dużo czasu ze względu na złożoność wielokątów. Widziałem złożone linie brzegowe (na przykład), które przez wieki testowały punkty znajdujące się w pobliżu ich granic, musiały powiększać wiele poziomów, aby sprawdzić, czy punkt znajduje się wewnątrz, czy na zewnątrz.
... abyś mógł wypróbować
.Reduce()
wielokąty i sprawdzić, czy to pomoże.Więcej informacji na temat tej funkcji można znaleźć na stronie http://msdn.microsoft.com/en-us/library/cc627410.aspx
źródło
Według dokumentów Microsoft indeksy przestrzenne będą używane z typami geograficznymi w następujących metodach, gdy pojawią się one na początku predykatu porównania z
WHERE
klauzulą:STIntersects
STDistance
STEquals
Tylko metody typów geometrii (lista zastrzeżona) wyzwalają użycie indeksu przestrzennego w
JOIN ... ON
, więc zmień kod na używanyWHERE geog1.STIntersects(geog2) = 1
i to powinno poprawić prędkość.Polecam również skorzystanie z porady w odpowiedzi g2server i dodanie poniższych elementów do filtrowania i dodania do niej indeksu przestrzennego
możesz mieć takie zapytanie jak poniżej (napisałem ten post szybko i jeszcze go nie testowałem, to jest po prostu coś do wypróbowania, ponieważ widziałem, że twoje zapytanie i najwyższe opublikowane odpowiedzi używają JOIN ON spatial op = 1, który nie użyje indeks przestrzenny):
FYI: Powyższe nie działa, jeśli
SimplePolysGeog
skończy się nakładanie (jak w szpilce może być w dwóch uproszczonych geogach, po prostu uruchomiłem to na ludziach w obwodzie w stanie, a ponieważ normalne polisy mają granicę, pola ograniczające się na siebie nakładają), więc w większości przypadków przypadki wyrzuci błąd, że podzapytanie zwróciło więcej niż jeden wynik.Z przeglądu indeksów przestrzennych MS Docs :
Następujące zapytanie będzie działać, jeśli się
SimplePolysGeogs
pokrywają:źródło