Pertanyaan yang mengembalikan dataset sangat besar di PostGIS


8

Saya memiliki permintaan PostGIS yang akan mengembalikan beberapa juta baris:

SELECT 
 t1.id AS id1,
 t2.id AS id2,
 ABS(t1.mean_h - t2.mean_h) AS h_diff, 
 ST_Distance(t1.the_geom, t2.the_geom) AS dist  
FROM tas_ponds as t1, tas_ponds as t2 
WHERE
 (t1.gid > t2.gid) AND
 ST_DWithin(t1.the_geom, t2.the_geom, 17000)

Saat dijalankan psql, saya mendapatkan out of memory for query resultkesalahan.

Googling menyarankan bahwa ini merupakan kesalahan dalam psql daripada postgres / PostGIS. Akankah mengubah kueri ke dalam formulir SELECT ... INTO x FROM ...memperbaiki masalah? Apakah ada pendekatan lain yang direkomendasikan untuk menangani dataset yang sangat besar?

Jawaban:


7

Beberapa orang mengaduk-aduk mengkonfirmasi bahwa ini adalah masalah klien Postgres, terlepas dari pertimbangan spasial atau server: klien memiliki jumlah memori yang terbatas untuk buffer hasilnya sebelum menampilkannya di layar, yang Anda melebihi.

Pendekatan yang disarankan untuk menangani ini adalah dengan menggunakan pendekatan DECLARE / FETCH untuk mengakses data dalam blok yang lebih kecil dari total hasil yang ditetapkan. Anda juga dapat membuat tampilan dengan komponen kueri (mis. Jarak) untuk mengurangi memori yang diperlukan untuk operasi kueri itu sendiri.


5

Saya mendapat dua menit, jadi saya tidak akan mengulangi jawabannya. Berikut adalah beberapa solusi yang mungkin:

  • Edit Memorybagian dari postgresql.conf. Cobalah untuk melihat apakah Anda memiliki pengaturan memori sangat rendah yang dapat mencegah kueri berjalan.

  • Cobalah untuk menulis kueri ke dalam file dan jalankan dari baris perintah, menggunakan:

    psql -f nama file db_name> output_file

  • Jika Anda bermaksud untuk menggunakan hasil dalam aplikasi eksternal, cobalah untuk menjalankan kueri menggunakan kursor dari luar psql. Misalnya, skrip Python yang akan menjalankan kueri Anda:

naskah:

try:
    conn = psycopg2.connect("dbname='' user='' host='' password=''") # Fill in
    cur = conn.cursor()
except:
        print 'Unable to connect to the database'
else:
        print 'Connected to database.'

query="""YOUR
         QUERY
         HERE"""
cur.execute(query)

Kursor dapat diubah, sehingga Anda dapat:

for result in cur:
    print result

Atau dapatkan semuanya:

 results=cur.fetchall()

2
Saya bisa saja salah, tetapi saya tidak berpikir solusi pertama (dan mungkin yang kedua) akan berhasil. Yang pertama memodifikasi memori server, dan ini adalah masalah klien, tidak terkait dengan memori yang tersedia dalam DMBS, dan yang kedua kemungkinan akan mengalami masalah yang sama kecuali jika hanya buffering ke layar adalah masalahnya. Solusi ketiga Anda lebih baik daripada IMO saya, karena memberikan kontrol halus dalam lingkungan yang fleksibel dengan kursor, yang sedikit lebih rumit dalam SQL mentah. +1
scw

@ CSW Anda mungkin benar tentang solusi pertama (dan mungkin kedua). Masalahnya adalah, kadang-kadang trik khusus ini tampaknya berfungsi dengan PostgreSQL, mereka mungkin meningkatkan kinerja umum, dan mereka membutuhkan sedikit waktu dan upaya untuk mencoba. Belajar banyak dari jawaban Anda.
Adam Matan

2

Sebagai catatan, dalam kasus saya menyimpan dataset yang dikembalikan di tabel lain menggunakan SELECT ... INTO ...sintaks bekerja.

Itu tidak hanya memecahkan masalah kehabisan memori, tetapi juga secara substansial lebih cepat dari permintaan asli.


1

Pengindeksan sangat penting dalam Postgres dan PostGIS

http://postgis.refractions.net/docs/ch04.html#id2794434

Rekomendasikan indeks GiST (Generalized Search Trees) untuk dataset yang sangat besar .... (juga "null safe") contoh CREATE INDEX [indexname] ON [tablename] MENGGUNAKAN GIST ([geometryfield]);

Setelah membangun indeks, penting untuk memaksa PostgreSQL untuk mengumpulkan statistik tabel, yang digunakan untuk mengoptimalkan rencana kueri

VACUUM ANALYZE [table_name] [column_name]; SELECT UPDATE_GEOMETRY_STATS ([table_name], [column_name]);

referensi yang bagus adalah: Mengambil Keuntungan dari Indeks http://postgis.refractions.net/docs/ch04.html#id2794685


Yap, saya mengindeks dan menyedot debu tabel, dan mengkonfirmasi indeks saya sedang digunakan melalui EXPLAIN, dll. Namun, masalah saya tidak dengan kecepatan (saat ini), dengan kesalahan memori yang tidak ada.
fmark
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.