Indeks przestrzenny PostgreSQL / PostGIS - brak przyspieszenia


15

Mam tabelę przestrzenną w bazie danych PostgreSQL / PostGIS. Każdy wiersz w nim reprezentuje wielokąt. Ma on następującą formę:

+----+--------+
|gid |   way  |
+----+--------+
|241 | 01030..|

Kolumna geometryczna to „droga”, która zawiera geometrię wielokąta. W WKT jest to: POLYGON ((„....”)). Robię dużo zapytań ST_Contains na tej tabeli, aby sprawdzić, czy dwa wielokąty są w sobie zawarte, np .:

Select ST_Contains(a.way, b.way) From table AS a, table AS b Where a.gid = 15 And b.gid = 16

Zastanawiałem się, jak przyspieszyć to zapytanie i dodałem indeks przestrzenny do tabeli:

CREATE INDEX table_way_gist ON table USING gist(way);

Ale tak naprawdę nie widzę przyspieszenia. Indeks tworzę PO wypełnieniu tabeli wszystkimi wielokątami PRZED wykonaniem zapytań ST_Contains. Czy indeks należy dodać przed wypełnieniem tabeli? Czy są jakieś specjalne wymagania dotyczące pracy z indeksem? Rzut (srid) geometrycznej kolumny jest ustawiony na 900913.

Używam: psql (PostgreSQL) 9.1.4 / POSTGIS = „1.5.3”

Odpowiedzi:


16

Najbardziej wydajnym indeksem dla zapytania wyrażonego w pytaniu jest indeks na gid, ponieważ jest to jedyna kolumna pojawiająca się w wyrażeniu where:

 CREATE INDEX table_gid ON table (gid);

Możesz bezpiecznie upuścić indeks gist, ponieważ będzie on zajmował tylko miejsce i spowalnia wstawianie / aktualizacje / usuwanie.

Długie wyjaśnienie

Jak powiedziałem, najskuteczniejszym indeksem w twoim przypadku jest indeks na gid, ponieważ pozwoli on silnikowi db szybciej pobierać wiersze (przy czym pobieranie jest zwykle najwolniejszą częścią procesu). Następnie prawdopodobnie lepiej obliczy wynik

  ST_Contains(a.way, b.way)

ekspresja bez patrzenia na indeks. Powodem jest to, że planista zapytań prawdopodobnie oszacuje, że dodatkowy koszt wyszukiwania indeksu gist w obu kolumnach w porównaniu z bezpośrednim wyszukiwaniem wartości a.way i b.way nie jest wart wysiłku, ponieważ całkowita liczba wierszy do wyszukania jest prawdopodobnie bardzo mały, szczególnie jeśli indeks jest unikalny.

Zasadniczo pamiętaj, że planista prawdopodobnie będzie faworyzował skanowanie tabeli zamiast skanowania indeksu w przypadku małych zestawów danych (rozmiary zestawów danych są szacowane na podstawie statystyk tabeli).


Sprawia to, że problem jest dla mnie bardziej jasny. Spróbuję. Więc jeśli wstawię zapytanie ST_Contains () do klauzuli WHERE, indeks przestrzenny powinien być rzeczywiście pomocny? Myślę, że muszę zreorganizować skrypt, aby wywoływał ST_Contains w klauzuli WHERE. W tej chwili iteruję przez wszystkie wielokąty i zawsze testuję dwa z nich osobno.
MichiMichbeck,

?? masz wrażenie, że indeks przestrzenny spowalnia rzeczy? To dla mnie nowość, ponieważ tam, gdzie pracuję, mamy indeksy przestrzenne dla każdego stołu i zastanawiam się, czy to zła praktyka
Luffydude

13

Jak powiedział unicoletti , indeks gist w kolumnie geometrii działałby tylko wtedy, gdy użyjesz ST_Contains () w wyrażeniu WHERE.

Na przykład, jeśli chcesz poznać wszystkie wielokąty, które się zawierają, możesz użyć czegoś takiego:

SELECT a.gid, b.gid
FROM table AS a, table as b
WHERE a.gid != b.gid and ST_Contains(a.way, b.way)

W takim przypadku, w zależności od wielkości tabeli i złożoności geometrii, indeks gist powinien zapewnić znaczne przyspieszenie, ponieważ ST_Contains rozpocznie od filtrowania wielokątów przez porównanie ich ramek granicznych, zanim faktycznie sprawdzi ich pełną geometrię. Możesz zobaczyć małe wyjaśnienie w samouczku OpenGeo .


Tak, rozumiem, potrzebuję tego zapytania, aby włączyć test granicy indeksu. Dziękuję Alexandre. (Oznaczę jako jedno rozwiązanie unicoletti, ponieważ był szybki i wyjaśnił mi problem)
MichiMichbeck,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.