Melakukan kueri kotak pembatas di PostGIS? [Tutup]

22

Saya memiliki tabel PostgreSQL, dengan hampir 2 juta baris, dengan bidang panjang-lat coordinatesdalam formulir POINT(-73.4938 33.2405).

Andaikata ada indeks geospasial pada bidang itu, apa cara tercepat dan paling efisien untuk memilih semua baris dalam kotak pembatas yang berubah-ubah?

Kotak adalah seperti SW long-lat: -74.0042 40.7688, NE long-lat: -73.8809 40.7984.

Avishai
sumber
Apakah koordinat yang Anda simpan sudah lama-lat atau mereka kisi-kisi (X, Y)?
Martin F
1
Matematika sederhana akan dilakukan di sini ... Jika point.x lebih besar dari SW.x dan lebih kecil dari NE.x dan point.y lebih besar dari SW.y dan lebih kecil dari NE.y pada saat yang sama, titik terletak di dalam MBR. Saya tidak tahu apakah ini lebih cepat daripada menggunakan kueri spasial. Anda keberatan mencoba?
Michal Zimmermann
@zimmi: Dia tidak benar-benar menyatakan bahwa item itu hanya poin; mereka bisa menjadi geometri yang kompleks.
Martin F
Mereka yang hanya poin, meskipun ;-). Mereka panjang dalam bentuk TITIK (-73.4938 33.24059) disimpan sebagai WKB.
Avishai
Saya mengedit Q (dan A saya) untuk mencerminkan info itu. :-)
Martin F

Jawaban:

24

Dengan asumsi batas kotak pembatas yang diberikan berada dalam sistem referensi spasial yang sama dengan koordinat yang tersimpan, dan Anda tahu operator spasial mana (berpotongan atau terkandung oleh) yang Anda butuhkan:

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)

Atau, jika Anda lebih suka suara "mengandung" (bukan "berisi oleh") WHEREklausa harus dibalik:

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

PS: Diberikan (oleh OP setelah penjelasan di atas) bahwa catatan adalah titik-titik sederhana, saya pikir perbedaan antara "berpotongan" dan "penahanan" menjadi sangat halus, hanya mempengaruhi titik-titik di tepi kotak pembatas.

Martin F
sumber
itu poin yang bagus. Berisi seharusnya baik-baik saja, karena Anda tidak akan benar-benar dapat melihat penanda peta jika berada di batas (mis., Kemungkinan browser chrome).
Avishai
What's the fastest ...?: OP
Magno C
Berhati-hatilah: &&dan @tampaknya tidak berfungsi saat berpotongan dengan poligon Geometri. Dalam hal ini, gunakan ST_Intersects(latlng_column,ST_GeomFromText('Polygon ((...))',4326))atau sebagai alternatifST_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
sumber
1
Tidak perlu mengatakan 4326 adalah SRID.
Magno C
2

Rupanya, saya tidak punya cukup poin untuk menambahkan komentar jadi saya menggunakan Jawaban ini hanya untuk mengatakan bahwa saya mencoba ST_MakeEnvelope vs matematika dibandingkan dengan "x> min_x dan x <max_x dan y> min_y dan y <max_y". ..pada rata-rata ST_MakeEnvelope mengambil 60 ms dan membandingkan matematika mengambil 155 ms pada permintaan bbox khusus saya.

Jadi pencarian spasial ST_MakeEnvelope harus lebih cepat daripada matematika dibandingkan!

Jason
sumber
1
Sebenarnya, jika Anda membuat indeks yang tepat min_x, max_x, min_y dan max_y akan jauh lebih cepat. Saya memiliki dataset yang sangat besar (lebih dari 3 juta poligon) dan melakukan keduanya INDEXpada ST_MakeEnvelope dan (ST_XMax, ST_XMin, ST_YMax, ST_YMin) dan perbedaannya sangat mendukung matematika. Math membawaku kurang dari 20-an (INDEX + Query) sementara persimpangan Envelope mengambil lebih dari 2 menit (aku menyerah ketika mencapai 2 menit, hanya 40-an untuk pengindeksan Spasial)
caiohamamura