Saya sedang membangun aplikasi yang seharusnya meminta dan mengembalikan setiap Record
dalam tabel yang berjarak beberapa X
kilometer dari PointX
. Records
dan PointX
posisi ditentukan dari (long/lat)
informasi yang disediakan oleh Google Geocode API.
Saya baru mengenal PostGIS. Setelah penelitian singkat, saya menemukan pertanyaan ini . Jawabannya sepertinya sejalan:
SELECT *
FROM your_table
WHERE ST_Distance_Sphere(the_geom, ST_MakePoint(your_lon,your_lat)) <= radius_mi * 1609.34
Masalahnya adalah: Meskipun saya baru memulai di GIS, ketika saya melihat kueri di atas, saya tidak bisa membayangkan bagaimana ini bisa menggunakan indeks. Ada 2 panggilan fungsi. Saya membayangkan tabel dipindai untuk setiap Record
. Saya ingin salah :)
Pertanyaan: Apakah PostGIS memiliki tipe indeks apa pun yang mampu membuat kinerja kueri di atas? Jika tidak, pendekatan apa yang direkomendasikan untuk melakukan apa yang saya butuhkan?
sumber
ST_SetSRID()
padaST_MakePoint
sebelum casting ke geografi dalam kueri.Jawaban:
Ada dua kunci untuk mendapatkan kinerja kueri geodetik yang baik dengan tabel besar dengan
geometry
kolom menggunakan data geografis WGS 1984 (SRID 4326):ST_DWithin
fungsi, yang mencari menggunakan indeks spasial yang tersedia, dan akan menemukan fitur geografi dengan jarak CartesianST_DWithin
bisa menggunakannyaJadi mari kita lihat apa yang terjadi di dunia nyata. Pertama, kita perlu membuat dan mengisi tabel satu juta poin acak:
Jika kami menjalankan kueri ST_Distance, kami mendapatkan pemindaian tabel lengkap yang diharapkan:
Sekarang, jika kita gunakan
ST_DWithin
, kita masih mendapatkan pemindaian tabel penuh (meskipun lebih cepat):Dan ini adalah bagian terakhir - Membangun indeks penutup (cast geography):
Akhirnya, pengoptimal menggunakan indeks spasial, dan itu menunjukkan, tapi apa tiga urutan besarnya antara teman?
Beberapa peringatan:
Saya seorang kutu buku basis data, jadi PC rumahan saya telah mendapat RAM 16Gb, enam core 3.3Ghz, dan SSD 256Gb untuk tablespace default basis data; jarak tempuh Anda dapat bervariasi
Saya menjalankan ulang pembuatan SQL sebelum setiap permintaan, untuk meratakan lapangan bermain sehubungan dengan halaman "panas" dalam cache, tetapi ini bisa menghasilkan hasil yang sedikit berbeda karena seed acak yang sama tidak digunakan untuk proses yang berbeda
Dan sebuah catatan:
sumber