ST_DWithin Calc Meters - transform or cast?

9

Saya ingin menggunakan ST_DWithin pada data yang disimpan dalam geometri SRID 4326 dan menggunakan meter sebagai parameter jarak. Apakah lebih efisien untuk melakukan pemeran (misalnya data.geom :: geografi) atau transformasi ke SRID dengan satuan meter (mis. ST_Transform (geom, 3857)? Atau tidak?

kingzing1
sumber
Berapa luas spasial data Anda?
DPSSpatial
Data mencakup seluruh Amerika Serikat.
kingzing1
Jika data yang diindeks bukan geografi maka Anda akan lebih baik mendekati dengan derajat dalam ST_DWithin, kemudian menggunakan gips dengan ST_Distance ..
Vince
Saya akan mencoba mengubah Albic Equal Area Conic untuk Continential USA, yang saya yakini dalam meter (meter?) ... coba pada beberapa fitur pertama ... di situlah saya akan mulai ...
DPSSpatial
bagaimana dengan "hanya mencoba mana yang lebih cepat"?
Stophface

Jawaban:

14

Seperti yang dijelaskan, jawabannya adalah "tidak", karena alasan berikut:

  • Ambil tabel spasial di 4326. Bangun indeks spasial di atasnya. Indeks spasial adalah indeks planar, yang terdiri dari batas-batas 2D fitur, pada 4326, diurutkan ke dalam struktur pohon.
  • (a) jalankan kueri filter jarak menggunakan gips, seperti ST_DWithin(geom::geography, %anothergeom, %radius). Karena geografi terlibat, sistem akan mencari indeks geografi (yang dibangun di atas bola, bukan di pesawat) dan tidak akan menemukannya. Karena tidak memiliki indeks, ia akan melakukan penggabungan menggunakan pemindaian penuh tabel. Itu akan lambat.
  • (B) menjalankan kueri filter jarak menggunakan transformasi, seperti ST_DWithin(ST_Transform(geom, 2163), %anothergeom, %radius). Tes Anda tidak bertentangan dengan kolom yang diindeks (geom), tetapi terhadap fungsi yang diterapkan pada kolom ( ST_Transform(geom,2163)) dan sekali lagi, indeks spasial Anda tidak akan digunakan. Itu akan lambat.

Anda perlu agar kueri dan indeks Anda selaras. Jika Anda tidak ingin mengubah proyeksi data Anda, Anda harus menggunakan indeks fungsional, misalnya, jika Anda membuat indeks geografi fungsi, Anda bisa menggunakan kueri berbasis geografi:

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

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

Atau, dalam kasus transformasi:

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

Performa tercepat mutlak adalah jika Anda mengonversi data dalam tabel Anda ke proyeksi planar (seperti EPSG: 2163 ), buat indeks spasial, dan kemudian gunakan ST_DWithin()pada hasilnya.

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
sumber
Terima kasih untuk Paul ini. Sangat membantu - secara dramatis mempercepat waktu untuk memproses.
kingzing1
Tetapi tidak akankah dua pertanyaan terakhir berbeda dari yang pertama di mana yang terakhir menghitung jarak planar, dan yang sebelumnya geodetik?
Andre Silva
Ini adalah jawaban yang bagus, tetapi yang membingungkan saya adalah rasanya seperti itu bertentangan dengan dokumen: postgis.net/docs/manual-dev/PostGIS_FAQ.html#idm1363 Apakah dokumen itu salah atau saya salah baca?
Olshansk