Realizando consulta de caixa delimitadora no PostGIS? [fechadas]

22

Eu tenho uma tabela do PostgreSQL, com quase 2 milhões de linhas, com um coordinatescampo de latência longa no formulário POINT(-73.4938 33.2405).

Supondo que exista um índice geoespacial nesse campo, qual é a maneira mais eficiente e rápida de selecionar todas as linhas dentro de uma caixa delimitadora arbitrária?

A caixa é como SW long-lat: -74.0042 40.7688, NE long-lat: -73.8809 40.7984.

Avishai
fonte
Suas coordenadas armazenadas já são de latão longo ou são grade (X, Y)?
Martin F
1
A matemática simples faria aqui ... Se point.x for maior que SW.xe menor que NE.xe point.y for maior que SW.y e menor que NE.y ao mesmo tempo, o ponto estará dentro do MBR. Não sei se é mais rápido do que usar consulta espacial. Você se importa de tentar?
Michal Zimmermann
@ zimmi: Na verdade, ele não afirma que os itens são apenas pontos; elas podem ser geometrias complexas.
Martin F
Mas são apenas pontos ;-). Eles são longos no formato POINT (-73.4938 33.24059) armazenados como WKB.
Avishai
Eu editei o Q (e meu A) para refletir essa informação. :-)
Martin F

Respostas:

24

Supondo que os limites das caixas delimitadoras estejam no mesmo sistema de referência espacial que as coordenadas armazenadas, e você sabe qual operador espacial (interseção ou contido por) é necessário:

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)

Como alternativa, se você preferir o som de "contém" (em vez de "contido por"), a WHEREcláusula deve ser invertida:

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

PS: Dado (pelo OP após o post acima) que os registros são pontos simples, acho que a diferença entre "interseções" e "contenção" se torna muito sutil, afetando apenas os pontos nas bordas da caixa delimitadora.

Martin F
fonte
este é um bom ponto. O conteúdo deve estar correto, pois você não poderá ver um marcador de mapa se ele estiver no limite (por exemplo, provavelmente o cromo do navegador).
Avishai
What's the fastest ...?: OP
Magno C
Esteja ciente: &&e @não parece funcionar ao cruzar com a geometria do polígono. Nesse caso, use ST_Intersects(latlng_column,ST_GeomFromText('Polygon ((...))',4326))ou alternativamente #ST_Contains
01/02 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
fonte
1
Não é necessário dizer que 4326 é o SRID.
Magno C
2

Aparentemente, não tenho pontos suficientes para adicionar um comentário, por isso estou usando esta resposta apenas para dizer que tentei ST_MakeEnvelope vs a comparação matemática de "x> min_x e x <max_x e y> min_y e y <max_y". ..em média, o ST_MakeEnvelope levou 60ms e a comparação matemática levou 155ms na minha consulta bbox específica.

Portanto, a pesquisa espacial ST_MakeEnvelope deve ser mais rápida que a matemática!

Jason
fonte
1
Na verdade, se você criar os índices corretos min_x, max_x, min_y e max_y, será muito mais rápido. Eu tenho um conjunto de dados muito grande (mais de 3 milhões de polígonos) e fiz tanto INDEXem ST_MakeEnvelope quanto em (ST_XMax, ST_XMin, ST_YMax, ST_YMin) e a diferença é enorme em favor da matemática. Math me levou menos de 20s (INDEX + query), enquanto intersecção Envelope assumiu 2min (eu desisti quando atingiu 2min 40s única para indexação espacial)
caiohamamura