ST_DWithin Calc Meter - transformieren oder gießen?

9

Ich möchte ST_DWithin für Daten verwenden, die in der SRID-Geometrie von 4326 gespeichert sind, und Meter als Abstandsparameter verwenden. Ist es effizienter, einen Cast (z. B. data.geom :: geography) oder eine Transformation in eine SRID mit Einheiten von Metern (z. B. ST_Transform (geom, 3857)) durchzuführen? Oder auch nicht?

kingzing1
quelle
Welche räumliche Ausdehnung haben Ihre Daten?
DPSSpatial
Die Daten decken die gesamten Vereinigten Staaten ab.
kingzing1
Wenn es sich bei den indizierten Daten nicht um geografische Daten handelt, sollten Sie sich in ST_DWithin mit Grad annähern und dann eine Besetzung mit ST_Distance verwenden.
Vince
Ich würde versuchen, mich für die kontinentalen USA in Albers Equal Area Conic umzuwandeln, was meiner Meinung nach in Metern (Metern?)
Angegeben ist. Probieren Sie
Was ist mit "nur versuchen, was schneller ist"?
Stophface

Antworten:

14

Wie beschrieben lautet die Antwort aus folgenden Gründen "weder":

  • Nehmen Sie eine räumliche Tabelle in 4326. Erstellen Sie einen räumlichen Index darauf. Der räumliche Index ist ein planarer Index, der aus den 2D-Grenzen der Merkmale in 4326 besteht und in eine Baumstruktur sortiert ist.
  • (a) Führen Sie eine Abstandsfilterabfrage mit einem Cast aus, wie z ST_DWithin(geom::geography, %anothergeom, %radius). Da es sich um eine Geografie handelt, sucht das System nach einem Geografieindex (der auf einer Kugel und nicht auf einer Ebene erstellt wird) und findet keinen. Da es keinen Index hat, führt es den Join mit vollständigen Scans der Tabelle (n) durch. Es wird langsam sein.
  • (b) Ausführen einer Abstandsfilterabfrage unter Verwendung einer Transformation wie ST_DWithin(ST_Transform(geom, 2163), %anothergeom, %radius). Ihre Tests richten sich nicht gegen die indizierte Spalte (geom), sondern gegen eine Funktion, die auf die Spalte ( ST_Transform(geom,2163)) angewendet wird. Daher wird Ihr räumlicher Index nicht verwendet. Es wird langsam sein.

Sie müssen Ihre Abfrage und Ihren Index harmonisieren. Wenn Sie die Projektion Ihrer Daten nicht ändern möchten, müssen Sie einen Funktionsindex verwenden. Wenn Sie beispielsweise einen Funktionsgeografieindex erstellen, können Sie eine geografiebasierte Abfrage verwenden:

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

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

Oder im Transformationsfall:

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);

Die absolut schnellste Leistung wird erzielt, wenn Sie die Daten in Ihrer Tabelle in eine planare Projektion (wie EPSG: 2163 ) konvertieren , einen räumlichen Index erstellen und dann ST_DWithin()für das Ergebnis verwenden.

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
quelle
Danke für diesen Paul. Sehr hilfreich - es beschleunigt die Bearbeitungszeit erheblich.
kingzing1
Aber unterscheiden sich die letzten beiden Abfragen nicht von der ersten, bei der letztere planare Entfernungen berechnen, und von den ersteren geodätischen?
Andre Silva
Dies ist eine großartige Antwort, aber was mich verwirrt, ist, dass es sich anfühlt, als würde es den Dokumenten widersprechen: postgis.net/docs/manual-dev/PostGIS_FAQ.html#idm1363 Sind die Dokumente falsch oder lese ich sie falsch?
Olshansk