Tworzę aplikację, która ma wysyłać zapytania i zwracać każdy Record
w tabeli X
oddalonej o kilometry PointX
. Records
i PointX
pozycje są określane na podstawie (long/lat)
informacji dostarczonych przez Google Geocode API.
Jestem nowy w PostGIS. Po szybkich badaniach znalazłem to pytanie . Wydaje się, że odpowiedź jest następująca:
SELECT *
FROM your_table
WHERE ST_Distance_Sphere(the_geom, ST_MakePoint(your_lon,your_lat)) <= radius_mi * 1609.34
Problem polega na tym: chociaż zaczynam dopiero w GIS, kiedy patrzę na powyższe zapytanie, nie mogę sobie wyobrazić, w jaki sposób można użyć indeksu. Istnieją 2 wywołania funkcji. Wyobrażam sobie, że stół jest skanowany dla każdego Record
. Chcę się mylić :)
Pytanie: Czy PostGIS ma jakiś typ indeksu zdolny do wykonania powyższego zapytania? Jeśli nie, jakie byłoby zalecane podejście do tego, czego potrzebuję?
postgis
postgresql
andrerpena
źródło
źródło
ST_SetSRID()
doST_MakePoint
zapytania przed rzutowaniem na geografię.Odpowiedzi:
Istnieją dwa klucze do uzyskania dobrej wydajności zapytań geodezyjnych w przypadku dużych tabel z
geometry
kolumnami korzystającymi z danych geograficznych WGS 1984 (SRID 4326):ST_DWithin
funkcji, która wyszukuje za pomocą dostępnego indeksu przestrzennego i znajdzie obiekty geograficzne z odległością kartezjańskąST_DWithin
możesz go użyćSpójrzmy więc na to, co dzieje się w prawdziwym świecie. Najpierw musimy utworzyć i wypełnić tabelę z milionem losowych punktów:
Jeśli wykonamy zapytanie ST_Distance, otrzymamy oczekiwany pełny skan tabeli:
Teraz, jeśli użyjemy
ST_DWithin
, nadal otrzymujemy pełny skan tabeli (choć szybszy):I to jest ostatni kawałek - Budowanie indeksu obejmującego (geografia obsady):
Wreszcie optymalizator korzysta z indeksu przestrzennego i pokazuje, ale jakie są trzy rzędy wielkości między przyjaciółmi?
Niektóre zastrzeżenia:
Jestem kujonem bazy danych, więc mój domowy komputer ma 16 GB pamięci RAM, sześć rdzeni 3,3 GHz i dysk SSD 256 GB dla domyślnego obszaru tabel bazy danych; twój przebieg może się różnić
Ponownie uruchomiłem kreację SQL przed każdym zapytaniem, aby wyrównać pole gry w odniesieniu do „gorących” stron w pamięci podręcznej, ale może to dać nieco inne wyniki, ponieważ ten sam losowy materiał źródłowy nie był używany dla różnych przebiegów
I uwaga:
źródło