Vous effectuez une requête de boîte englobante dans PostGIS? [fermé]

22

J'ai une table PostgreSQL, avec près de 2 millions de lignes, avec un coordinateschamp long-lat dans le formulaire POINT(-73.4938 33.2405).

En supposant qu'il existe un index géospatial sur ce champ, quel est le moyen le plus efficace et le plus rapide pour sélectionner toutes les lignes dans un cadre de sélection arbitraire?

La boîte est comme SW long-lat: -74.0042 40.7688, NE long-lat: -73.8809 40.7984.

Avishai
la source
Vos coordonnées stockées sont-elles déjà longues-lat ou sont-elles des grilles (X, Y)?
Martin F
1
Des mathématiques simples feraient l'affaire ici ... Si point.x est plus grand que SW.x et plus petit que NE.x et point.y est plus grand que SW.y et plus petit que NE.y en même temps, le point se trouve à l'intérieur du MBR. Je ne sais pas si c'est plus rapide que d'utiliser une requête spatiale. Ça vous dérange d'essayer?
Michal Zimmermann
@zimmi: Il ne déclare pas en fait que les articles ne sont que des points; il peut s'agir de géométries complexes.
Martin F
Ce ne sont que des points ;-). Ils sont à lat longue sous la forme POINT (-73.4938 33.24059) stockés en tant que WKB.
Avishai
J'ai édité le Q (et mon A) pour refléter cette information. :-)
Martin F

Réponses:

24

En supposant que les limites du cadre de délimitation données se trouvent dans le même système de référence spatiale que les coordonnées stockées et que vous savez de quel opérateur spatial (intersecté ou contenu par) vous avez besoin:

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)

Alternativement, si vous préférez le son de "contient" (au lieu de "contenu par"), la WHEREclause doit être inversée:

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

PS: Étant donné (par OP après la publication de ce qui précède) que les enregistrements sont de simples points, je pense que la différence entre "intersections" et "confinement" devient très subtile, n'affectant que les points sur les bords de la boîte englobante.

Martin F
la source
c'est un bon point. Le contenu devrait être correct, car vous ne pourrez pas vraiment voir un marqueur de carte s'il se trouve sur la frontière (c'est-à-dire, le navigateur chrome probablement).
Avishai
What's the fastest ...?: OP
Magno C
Soyez conscient: &&et @ne semble pas fonctionner lors de l'intersection avec la géométrie du polygone. Dans ce cas, utilisez ST_Intersects(latlng_column,ST_GeomFromText('Polygon ((...))',4326))ou alternativementST_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
la source
1
Pas besoin de dire que 4326 est le SRID.
Magno C
2

Apparemment, je n'ai pas assez de points pour ajouter un commentaire, donc j'utilise cette réponse juste pour dire que j'ai essayé à la fois ST_MakeEnvelope et la comparaison mathématique de "x> min_x et x <max_x et y> min_y et y <max_y". ..en moyenne, ST_MakeEnvelope a pris 60 ms et la comparaison mathématique a pris 155 ms sur ma requête bbox particulière.

La recherche spatiale ST_MakeEnvelope devrait donc être plus rapide que les mathématiques ne le comparent!

Jason
la source
1
En fait, si vous créez les bons index, min_x, max_x, min_y et max_y seront beaucoup plus rapides. J'ai un très grand ensemble de données (plus de 3 millions de polygones) et l'ai fait à la fois INDEXsur ST_MakeEnvelope et (ST_XMax, ST_XMin, ST_YMax, ST_YMin) et la différence est très favorable aux mathématiques. Les mathématiques m'ont pris moins de 20s (INDEX + Query) tandis que l'intersection d'enveloppe a pris plus de 2min (j'ai abandonné quand elle a atteint 2min, 40s seulement pour l'indexation spatiale)
caiohamamura