ST_DDans Calc Mètres - transformer ou lancer?

9

Je veux utiliser ST_DWithin sur des données qui sont stockées dans la géométrie SRID de 4326 et utiliser des mètres comme paramètre de distance. Est-il plus efficace de faire un cast (par exemple data.geom :: geography) ou une transformation en un SRID avec des unités de mètres (par exemple ST_Transform (geom, 3857)? Ou ni l'un ni l'autre?

kingzing1
la source
Quelle est l'étendue spatiale de vos données?
DPSSpatial
Les données couvrent l'ensemble des États-Unis.
kingzing1
Si les données indexées ne sont pas géographiques, vous feriez mieux d'approximer avec les degrés dans ST_DDans, puis d'utiliser un plâtre avec ST_Distance ..
Vince
J'essaierais de me transformer en Albers Equal Area Conic for the Continential USA, qui je crois est en mètres (mètres?) ... essayez-le d'abord sur quelques fonctionnalités ... c'est là que je commencerais ...
DPSSpatial
qu'en est-il de "juste essayer ce qui est plus rapide"?
Stophface

Réponses:

14

Comme décrit, la réponse est "ni", pour les raisons suivantes:

  • Prenez une table spatiale en 4326. Construisez un index spatial dessus. L'index spatial est un index plan, constitué des limites 2D des entités, en 4326, triées en une structure arborescente.
  • (a) exécuter une requête de filtre de distance à l'aide d'un cast, comme ST_DWithin(geom::geography, %anothergeom, %radius). Parce que la géographie est impliquée, le système recherchera un index de géographie (qui est construit sur une sphère, pas sur un plan) et n'en trouvera aucun. Puisqu'il n'a pas d'index, il effectuera la jointure en utilisant des analyses complètes des tables. Ce sera lent.
  • (b) exécuter une requête de filtre de distance en utilisant une transformation, comme ST_DWithin(ST_Transform(geom, 2163), %anothergeom, %radius). Vos tests ne sont pas contre la colonne indexée (geom), mais contre une fonction appliquée à la colonne ( ST_Transform(geom,2163)) et donc encore une fois, votre index spatial ne sera pas utilisé. Ce sera lent.

Vous avez besoin que votre requête et votre index s'harmonisent. Si vous ne souhaitez pas modifier la projection de vos données, vous devrez utiliser un index fonctionnel, par exemple, si vous créez un index géographique de fonction, vous pouvez utiliser une requête basée sur la géographie:

CREATE INDEX mytable_geog_x 
  ON mytable USING GIST (geography(geom));

SELECT * 
  FROM mytable 
  WHERE ST_DWithin(geography(geom), %anothergeography, %radius);

Ou, dans le cas de la transformation:

CREATE INDEX mytable_geog_x 
  ON mytable USING GIST (ST_Transform(geom, 2163));

SELECT * 
  FROM mytable 
  WHERE ST_DWithin(ST_Transform(geom, 2163), %another2163geometry, %radius);

La performance la plus rapide absolue sera si vous convertissez les données de votre table en projection planaire (comme EPSG: 2163 ), créez un index spatial, puis utilisez ST_DWithin()le résultat.

ALTER TABLE mytable 
  ALTER COLUMN geom 
  TYPE Geometry(Point, 2163) 
  USING ST_Transform(geom, 2163);

CREATE INDEX mytable_geom_x ON mytable USING GIST (geom);

SELECT * 
  FROM mytable
  WHERE ST_DWithin(geom, %some2163geom, %radius)
Paul Ramsey
la source
Merci pour ça Paul. Très utile - il accélère considérablement le temps de traitement.
kingzing1
Mais les deux dernières requêtes ne seront-elles pas différentes de la première dans laquelle ces dernières calculent les distances planes et les anciennes géodésiques?
Andre Silva
C'est une excellente réponse, mais ce qui m'embrouille, c'est que j'ai l'impression de contredire les documents: postgis.net/docs/manual-dev/PostGIS_FAQ.html#idm1363 Les documents sont-ils incorrects ou les ai-je mal interprétés?
Olshansk