Nie mogę uruchomić PostGIS 2.1 na PostgreSQL 9.3.5 do korzystania z indeksu przestrzennego nawet dla najprostszych zapytań. Cały zestaw danych jest 8 milionów punktów (siatka liczba ludności stąd) . Tabela jest tworzona jako
CREATE TABLE points (
population DOUBLE PRECISION NOT NULL,
location GEOGRAPHY(4326, POINT) NOT NULL
)
CREATE INDEX points_gix ON points USING GIST(location);
Zapytania są tak proste, jak tylko się da
SELECT SUM(population)
FROM points
WHERE ST_Distance(
location,
ST_GeographyFromText('SRID=4326; POINT(0 0)')
) < 1000
PostgreSQL zawsze używa do tego skanowania Seq, próbowałem podzestawu z 10000 punktami - nadal skanowanie Seq. Jakieś pomysły?
Odpowiedzi:
ST_Distance faktycznie oblicza odległość między wszystkimi parami punktów, więc jako taki nie można zastosować żadnego indeksu. Twoje zapytanie wykona skanowanie sekwencji, a następnie wybierze te geometrie, które są mniejsze niż podana odległość. Szukasz ST_DWithin , który korzysta z indeksu.
ST_Distance jest bardziej przydatny do zamawiania wyników, często w połączeniu z ORDER BY i / lub LIMIT, które zostały uzyskane przy zapytaniach korzystających z indeksu.
źródło
Jak powiedział @ JohnPowellakaBarça,
ST_DWithin()
jest to droga do zrobienia, gdy chcesz poprawności .Jednak w moim przypadku chcę tylko przybliżone oszacowanie, więc nawet
ST_DWithin()
było zbyt drogie (koszt zapytania) na moje potrzeby. Zamiast tego użyłem&&
iST_Expand(box2d)
(nie myl tego zgeometry
wersją). Przykład:To, co natychmiast stanie się oczywiste, to fakt, że mamy do czynienia ze stopniami zamiast z licznikami i używamy obwiedni zamiast koła w sferoidie. W moim przypadku skraca się to z 24 ms do zaledwie 2 ms (lokalnie w SSD). Jednak w przypadku mojej produkcyjnej bazy danych w AWS RDS PostgreSQL ze współbieżnymi połączeniami i mało hojnymi limitami IOPS (100 IOPS) pierwotne
ST_DWithin()
zapytanie wydaje zbyt dużo IOPS i może wykonać ponad 2000 ms, a nawet gorzej, gdy limit IOPS zostanie wyczerpany.To nie jest dla wszystkich, ale jeśli możesz poświęcić trochę dokładności dla prędkości (lub aby zaoszczędzić IOPS), to podejście może być dla ciebie. Jak widać na poniższych planach zapytań,
ST_DWithin
nadal wymaga ono filtru przestrzennego wewnątrz skanowania stosu bitmap oprócz Recheck Cond, podczas gdy&&
geometria pudełka nie wymaga filtra i używa tylko Recheck Cond.Zauważyłem również, że to ma
IS NOT NULL
znaczenie, bez niego pozostaniesz z gorszym planem zapytań. Wydaje się, że indeks GIST nie jest do tego wystarczająco „inteligentny”. (oczywiście nie jest to konieczne, jeśli twoja kolumna jestNOT NULL
, w moim przypadku jest wNULL
stanie)Tabela 20000 wierszy
ST_DWithin(geography, geography, 100000, FALSE)
na AWS RDS 512 MB RAM z 300 IOPS:Tabela 20000 wierszy
&&
iST_Expand(box2d)
na AWS RDS 512 MB RAM z 300 IOPS:Ponownie z prostszym zapytaniem:
Tabela 20000 wierszy
ST_DWithin(geography, geography, 100000, FALSE)
na AWS RDS 512 MB RAM z 300 IOPS:Tabela 20000 wierszy
&&
iST_Expand(box2d)
na AWS RDS 512 MB RAM z 300 IOPS:źródło