Saya memiliki data OpenStreetMap untuk Belanda yang dimuat ke dalam database PostGIS (PostgreSQL 8.3 / PostGIS 1.3.3) menggunakan skema osmosis . Ini berarti semua tag disimpan di bidang hstore . Selain indeks GIST yang dibuat osmosis pada bidang geometri, saya membuat indeks GIST tambahan pada bidang tag.
Mencoba membuat kueri menggunakan batasan spasial dan batasan pada bidang tag, saya menemukan bahwa ini lebih lambat daripada yang saya inginkan. Kueri seperti ini:
SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n
INNER JOIN users AS u ON n.user_id = u.id
WHERE tags->'man_made'='surveillance'
AND ST_Within(geom, ST_GeomFromText('POLYGON((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326));
Dibutuhkan 22 detik untuk mengembalikan 78 catatan.
Ada sekitar 53 juta catatan dalam tabel ini.
Apakah ada cara untuk mempercepat ini secara signifikan? Saya pernah mendengar bahwa hstore diimplementasikan secara signifikan lebih baik di PostgreSQL 9, akankah meningkatkan bantuan?
Jawaban:
Salah satu metode adalah dengan menanyakan tag yang Anda minati dan menempatkan catatan tersebut di tabel baru. Maka Anda hanya perlu meminta tabel baru alih-alih semua 53 juta catatan. Jika Anda mencoba untuk memperbarui basis data Anda, Anda bisa menjalankan kueri ini setiap kali Anda mendapatkan data baru dari OSM.
sumber
Anda dapat mencoba membuat indeks untuk kolom hstore Anda,
dan kemudian gunakan
?
operator untuk membatasi kueri hanya pada baris itu:sumber
?
operator membutuhkan waktu 48 detik dibandingkan dengan 88 detik untuk permintaan saya (saya tidak tahu bagaimana saya mendapat 72 detik kemarin, mungkin mesin melakukan sesuatu yang rumit saat ini ketika saya melakukan query). Jadi masih bukan kinerja yang saya cari, tapi saya mendapatkan pemahaman yang lebih dalam tentang bagaimana indeks GIST beroperasi pada kolom hstore. Saya masih harus pergi dengan solusi lain untuk menciptakan pandangan terwujud untuk mendapatkan kinerja yang saya inginkan.Fungsi st_within dan _st_within tidak dikenal karena kecepatannya. Operator && mungkin membantu karena akan memeriksa kotak bukan geometri
Anda dapat mencoba yang berikut ini:
Untuk kiat kinerja lebih lanjut, periksa: http://postgis.refractions.net/docs/ch06.html
sumber
Masalah dengan permintaan Anda adalah
tags->'man_made'='surveillance'
klausa. Ini memaksa Postgres untuk memperluas tag hstore dan tidak mengizinkannya untuk menggunakan indeks. Jika Anda menulis ulang ini menggunakan@>
(mengandung) itu akan memungkinkan penggunaan indeks.Karena Anda meminta persegi panjang, Anda dapat menggunakan
&&
sebagai ganti ST_Within. Ini akan memiliki keuntungan kecil, karena ST_Within tidak rumit untuk dievaluasi, dan ST_Within secara implisit melakukan&&
pemeriksaan.Peningkatan kecepatan tambahan akan menggunakan indeks GIN pada tag, bukan indeks GIST. Indeks GIN membutuhkan waktu lebih lama untuk dibangun tetapi lebih cepat.
Seluruh kueri akan menjadi
SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n INNER JOIN users AS u ON n.user_id = u.id WHERE tags @> hstore('man_made', 'surveillance') AND geom && ST_GeomFromText('POLYGON((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326);
Jika Anda tahu Anda akan sering meminta tag tertentu, Anda dapat membuat sebagian indeks dengan itu
CREATE INDEX ON nodes ( tags->'man_made' ) WHERE (tags->'man_made' IS NOT NULL);
.Ini akan memungkinkan kondisi WHERE
tags->'man_made'='surveillance'
untuk menggunakan indeks. Sayangnya, indeks itu tidak dapat membantu@>
kueri dan indeks GIN atau GIST tidak dapat membantutags->'foo'
kueri, jadi Anda harus mencocokkan kueri dengan indeks yang Anda miliki.sumber
tags @>hstore()
kueri saya secara besar-besaran, terima kasih.coba ini sebagai gantinya:
PILIH n.geom, n.tags, n.tstamp, u.name DARI node AS n INNER GABUNG pengguna SEBAGAI ON n.user_id = u.id WHERE tags @> 'man_made => surveillance' :: hstore AND ST_Within (geom , ST_GeomFromText ('POLYGON ((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))', 4326));
sumber