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”

MichiMichbeck
źródło

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).

unicoletti
źródło
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 .

Alexandre Neto
źródło
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,