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:
- Membuat kisi 50 km di atas Inggris menggunakan solusi ST_FishNet yang disarankan di sini
- Atur SRID dari grid yang dihasilkan ke British National Grid dan buat indeks spasial di atasnya
- 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
- Memotong data titik saya menggunakan kisi yang sama
- 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:
Namun posting klipingnya terlihat seperti ini:
Ini adalah contoh dari poligon "hilang":
sumber
Jawaban:
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
Anda akan melihat sesuatu seperti, setelah kehilangan banyak detail:
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.
sumber