Czy wykonujesz zapytanie do ramki ograniczającej w PostGIS? [Zamknięte]

22

Mam tabelę PostgreSQL, z prawie 2 milionami wierszy, z długim coordinatespolem w formie POINT(-73.4938 33.2405).

Załóżmy, że istnieje indeks geoprzestrzenny na tym polu, jaki jest najbardziej wydajny i najszybszy sposób na zaznaczenie wszystkich wierszy w dowolnym polu ograniczającym?

Pudełko jest niczym SW long-lat: -74.0042 40.7688, NE long-lat: -73.8809 40.7984.

Avishai
źródło
Czy przechowywane współrzędne są już długo-długie, czy są to siatki (X, Y)?
Martin F
1
Przydałaby się tutaj prosta matematyka ... Jeśli point.x jest większy niż SW.x i mniejszy niż NE.xi point.y jest większy niż SW.y i mniejszy niż NE.y w tym samym czasie, punkt leży wewnątrz MBR. Nie wiem jednak, czy jest to szybsze niż używanie zapytania przestrzennego. Masz ochotę spróbować?
Michał Zimmermann
@zimmi: W rzeczywistości nie stwierdza, że ​​przedmioty tylko punktami; mogą to być złożone geometrie.
Martin F
to tylko punkty ;-). Są długo-łacińskie w formie POINT (-73.4938 33.24059) przechowywane jako WKB.
Avishai
Edytowałem Q (i moje A), aby odzwierciedlić te informacje. :-)
Martin F

Odpowiedzi:

24

Zakładając, że podane granice ramki granicznej znajdują się w tym samym systemie odniesienia przestrzennego, co zapisane współrzędne, i wiesz, którego operatora przestrzennego (przecina lub zawiera) potrzebujesz:

SELECT *
FROM   my_table
WHERE  coordinates 
    && -- intersects,  gets more rows  -- CHOOSE ONLY THE
    @ -- contained by, gets fewer rows -- ONE YOU NEED!
    ST_MakeEnvelope (
        xmin, ymin, -- bounding 
        xmax, ymax, -- box limits
        my_srid)

Alternatywnie, jeśli wolisz dźwięk „zawiera” (zamiast „zawiera”), WHEREklauzula powinna zostać odwrócona:

WHERE  ST_MakeEnvelope (...)
    ~ -- contains, gets same fewer rows 
    coordinates 

PS: Biorąc pod uwagę (przez OP po opublikowaniu powyższego), że rekordy prostymi punktami, myślę, że różnica między „przecięciami” a „ograniczeniem” staje się bardzo subtelna, wpływając tylko na punkty na krawędzi ramki ograniczającej.

Martin F.
źródło
trafne spostrzeżenie. Zawartość powinna być w porządku, ponieważ tak naprawdę nie będziesz w stanie zobaczyć znacznika mapy, jeśli znajduje się na granicy (tzn. Prawdopodobnie w przeglądarce Chrome).
Avishai
What's the fastest ...?: OP
Magno C
Uważaj: &&i @wydaje się, że nie działa, gdy przecina się z geometrią wielokąta. W takim przypadku użyj ST_Intersects(latlng_column,ST_GeomFromText('Polygon ((...))',4326))lub alternatywnieST_Contains
Alex
4
SELECT ST_Y(the_geom) AS latitude, ST_X(the_geom) as longitude
from units u where the_geom && ST_MakeEnvelope(left, bottom, right, top, 4326)
Magno C.
źródło
1
Nie trzeba dodawać, że 4326 to SRID.
Magno C
2

Najwyraźniej nie mam wystarczającej liczby punktów, aby dodać komentarz, więc używam tej odpowiedzi tylko po to, aby powiedzieć, że wypróbowałem zarówno ST_MakeEnvelope vs. ..średnio ST_MakeEnvelope zajęło 60 ms, a porównanie matematyki zajęło 155 ms dla mojego konkretnego zapytania bbox.

Tak więc wyszukiwanie przestrzenne ST_MakeEnvelope powinno być szybsze niż porównanie matematyki!

Jason
źródło
1
W rzeczywistości, jeśli utworzysz odpowiednie indeksy, min_x, max_x, min_y i max_y będą znacznie szybsze. Mam bardzo duży zestaw danych (ponad 3 miliony wielokątów) i zarówno INDEXw ST_MakeEnvelope, jak i (ST_XMax, ST_XMin, ST_YMax, ST_YMin), a różnica jest bardzo korzystna dla matematyki. Matematyka zajęła mi mniej niż 20 sekund (INDEKS + zapytanie), podczas gdy przecięcie kopert zajęło 2 minuty (poddałem się, gdy osiągnęło 2
minuty