Mengoptimalkan titik yang sangat besar dalam kueri poligon


9

Saya memiliki dataset nasional tentang titik alamat (37 juta) dan dataset poligon garis banjir (2 juta) tipe MultiPolygonZ, beberapa poligon sangat kompleks, maks ST_NPoints sekitar 200.000. Saya mencoba mengidentifikasi menggunakan PostGIS (2.18) yang titik alamatnya berada dalam poligon banjir dan menuliskannya ke tabel baru dengan id alamat dan perincian risiko banjir. Saya telah mencoba dari perspektif alamat (ST_Within) tetapi kemudian bertukar ini mulai dari perspektif area banjir (ST_Contains), alasannya adalah bahwa ada area besar tanpa risiko banjir sama sekali. Kedua set data telah diproyeksikan ke 4326 dan kedua tabel memiliki indeks spasial. Permintaan saya di bawah ini telah berjalan selama 3 hari sekarang dan tidak menunjukkan tanda-tanda akan selesai dalam waktu dekat!

select a.id, f.risk_factor_1, f.risk_factor_2, f.risk_factor_3
into gb.addresses_with_flood_risk
from gb.flood_risk_areas f, gb.addresses a
where ST_Contains(f.the_geom, a.the_geom);

Apakah ada cara yang lebih optimal untuk menjalankan ini? Juga, untuk pertanyaan jangka panjang dari jenis ini apa cara terbaik untuk memantau kemajuan selain dari melihat pemanfaatan sumber daya dan pg_stat_activity?


Permintaan awal saya selesai OK meskipun selama 3 hari dan saya teralihkan dengan pekerjaan lain sehingga saya tidak pernah mendedikasikan waktu untuk mencoba solusinya. Namun saya baru saja mengunjungi kembali ini dan bekerja melalui rekomendasi, sejauh ini bagus. Saya telah menggunakan yang berikut ini:

  1. Membuat kisi 50 km di atas Inggris menggunakan solusi ST_FishNet yang disarankan di sini
  2. Atur SRID dari grid yang dihasilkan ke British National Grid dan buat indeks spasial di atasnya
  3. Memotong data banjir saya (MultiPolygon) menggunakan ST_Intersection dan ST_Intersects (hanya Gotcha di sini adalah saya harus menggunakan ST_Force_2D pada geom karena shape2pgsql menambahkan indeks Z
  4. Memotong data titik saya menggunakan kisi yang sama
  5. Membuat indeks pada baris dan kolom dan indeks spasial pada masing-masing tabel

Saya siap menjalankan skrip saya sekarang, akan mengulangi baris dan kolom yang mengisi hasil ke dalam tabel baru sampai saya telah mencakup seluruh negara. Tetapi baru saja memeriksa data banjir saya dan beberapa poligon yang sangat besar tampaknya telah hilang dalam terjemahan! Ini permintaan saya:

SELECT g.row, g.col, f.gid, f.objectid, f.prob_4band, ST_Intersection(ST_Force_2D(f.geom), g.geom) AS geom 
INTO rofrse.tmp_flood_risk_grid 
FROM rofrse.raw_flood_risk f, rofrse.gb_grid g
WHERE (ST_Intersects(ST_Force_2D(f.geom), g.geom));

Data asli saya terlihat seperti ini:

Data banjir asli

Namun posting klipingnya terlihat seperti ini:

Data banjir kotak

Ini adalah contoh dari poligon "hilang":

Poligon "Hilang"


Saya baru menyadari bahwa kami bertemu di FOSS4G di Seoul dan berbicara tentang keajaiban hub pencari ESRI :-)
John Powell

Apakah Anda pernah menyelesaikan pendekatan membagi dan menaklukkan? Bisakah Anda memperbarui waktu benchmark dengan pendekatan ini?
andrew

Jawaban:


6

Untuk menjawab pertanyaan terakhir Anda terlebih dahulu, lihat posting initentang keinginan untuk dapat memantau kemajuan permintaan. Masalahnya sulit dan akan diperparah dalam kueri spasial, karena mengetahui bahwa 99% dari alamat telah dipindai untuk penahanan dalam poligon banjir, yang bisa Anda dapatkan dari penghitung lingkaran dalam implementasi pemindaian tabel yang mendasarinya, belum tentu membantu jika 1% akhir alamat terjadi untuk memotong poligon banjir dengan titik terbanyak, sedangkan 99% sebelumnya memotong beberapa area kecil. Ini adalah salah satu alasan mengapa EXPLAIN kadang-kadang bisa tidak membantu dengan spasial, karena memberikan indikasi baris yang akan dipindai, tetapi, untuk alasan yang jelas, tidak memperhitungkan kompleksitas poligon (dan karenanya sebagian besar dari run time) dari setiap tipe intersect / intersection.

Masalah kedua adalah jika Anda melihat sesuatu seperti

EXPLAIN 
SELECT COUNT(a.id) 
FROM sometable a, someothertable b
WHERE ST_Intersects (a.geom, b.geom)

Anda akan melihat sesuatu seperti, setelah kehilangan banyak detail:

_st_intersects(a.geom, b.geom)
   ->  Bitmap Index Scan on ix_spatial_index_name  (cost...rows...width...))
   Index Cond: (a.geom && geom)

Kondisi terakhir, &&, berarti melakukan centang pada kotak pembatas, sebelum melakukan persimpangan yang lebih akurat dari geometri yang sebenarnya. Ini jelas masuk akal dan merupakan inti dari cara kerja R-Trees. Namun, dan saya juga bekerja pada data banjir Inggris di masa lalu, jadi saya akrab dengan struktur data, jika (Multi) Poligon sangat luas - masalah ini sangat akut jika sungai mengalir, katakanlah, 45 derajat - Anda mendapatkan kotak pembatas besar, yang mungkin memaksa sejumlah besar persimpangan potensial untuk diperiksa pada poligon yang sangat kompleks.

Satu-satunya solusi yang saya dapat untuk masalah "permintaan saya telah berjalan selama 3 hari dan saya tidak tahu apakah kita berada pada 1% atau 99%" masalah adalah dengan menggunakan semacam membagi dan menaklukkan untuk boneka. pendekatan, maksud saya, memecah daerah Anda menjadi potongan-potongan kecil, dan menjalankannya secara terpisah, baik dalam satu lingkaran di plpgsql atau secara eksplisit di konsol. Ini memiliki keuntungan memotong poligon kompleks menjadi beberapa bagian, yang berarti titik selanjutnya dalam pemeriksaan poligon bekerja pada poligon yang lebih kecil dan kotak pembatas poligon jauh lebih kecil.

Saya telah berhasil menjalankan kueri dalam satu hari dengan memecah Inggris menjadi 50km dengan 50km blok, setelah membunuh permintaan yang telah berjalan selama lebih dari seminggu di seluruh Inggris. Selain itu, saya harap pertanyaan Anda di atas adalah CREATE TABLE atau UPDATE dan bukan hanya SELECT. Ketika Anda memperbarui satu tabel, alamat, berdasarkan pada poligon banjir, Anda harus memindai seluruh tabel yang diperbarui, alamat, jadi sebenarnya memiliki indeks spasial di atasnya sama sekali tidak membantu.

EDIT: Atas dasar bahwa suatu gambar bernilai seribu kata, berikut adalah gambar dari beberapa data banjir Inggris. Ada satu multipolygon yang sangat besar, kotak pembatas yang mencakup seluruh area itu, sehingga mudah untuk melihat bagaimana, misalnya, dengan terlebih dahulu memotong poligon banjir dengan kotak merah, kotak di sudut barat daya tiba-tiba hanya akan diuji terhadap subset kecil poligon.

masukkan deskripsi gambar di sini


Hai John dan terima kasih banyak atas jawaban komprehensifnya, saya akan mengikuti rekomendasi Anda pada pendekatan grid, terdengar seperti saran yang sangat masuk akal, saya tidak benar-benar ingin menyederhanakan dan kehilangan keakuratan. Saya akan melakukan benchmark dengan satu blok dan kemudian berjalan secara paralel, jauh lebih mudah hari ini dengan cloud! Terima kasih lagi
Mark Varley

Hai Mark, jangan khawatir, tolong pertimbangkan untuk menerima jawabannya jika Anda merasa itu membantu. Ini membantu menjaga situs tetap bersih, pertanyaan tanpa jawaban yang diterima adalah salah satu metrik yang dilihat oleh situs pertukaran bertumpuk.
John Powell

OK semua selesai, ini adalah posting pertama saya di sini, saya biasanya menemukan jawaban dari utas terperinci dan tanggapan yang membantu. Permintaan akhirnya selesai pagi ini setelah sekitar 3 hari yang tidak terlalu buruk tetapi akan mengikuti saran Anda hari ini dan memecahnya menjadi potongan-potongan untuk kinerja yang lebih baik. Sekali lagi terima kasih atas bantuan Anda, John dan mungkin melihat Anda di Bonn pada bulan Agustus!
Mark Varley

Saya menambahkan foto, meskipun saya sadar Anda sudah mendapatkan fotonya: D, mungkin membantu orang lain memvisualisasikan apa yang sedang saya bicarakan. Ya, saya hampir pasti akan ke Foss4G UK, dan akan memikirkan Bonn.
John Powell
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.