Saya mencoba menghitung beberapa statistik untuk data OSM menggunakan PostgreSQL 9.3.5 dan PostGIS 2.1.4. Saya mulai dengan ekstrak bavaria kecil yang saya unduh dari Geofabrik. Skema db adalah skema normal 0,6 API, data diimpor melalui pendekatan dump ke Postgres (menggunakan skrip pgsnapshot_schema_0.6 * .sql yang datang dengan osmosis). VACUUM ANALYZE juga dilakukan.
Satu-satunya hal yang dibuat khusus yang saya gunakan adalah tabel poligon yang berisi multipoligon untuk semua hubungan batas administratif. Geometri poligon tidak disederhanakan dengan cara apa pun.
Apa yang sekarang saya coba capai adalah menghitung semua node yang ada di dalam admin = 6 batas bavaria. Ini query SQL saya:
SELECT relpoly.id, count(node)
FROM bavaria.relpolygons relpoly, bavaria.nodes node
WHERE relpoly.tags @> '"boundary"=>"administrative","admin_level"=>"6"'::hstore
AND ST_Intersects(relpoly.geom, node.geom)
GROUP BY relpoly.id;
Runtime dari query ini mengerikan karena Postgres melakukan loop bersarang bergabung dan memindai semua node untuk setiap admin = 6 batas. FYI, bavaria dibagi menjadi 98 admin = 6 poligon dan ada sekitar 30 juta node dalam ekstrak bavaria.
Apakah mungkin untuk menghindari eksekusi query sub-optimal ini dan memberi tahu Postgres bahwa ia harus memindai semua node hanya sekali (misalnya, dengan menambah penghitung untuk poligon yang sesuai di set hasil atau dengan menggunakan petunjuk)?
Edit:
1) indeks spasial ada pada node bavaria:
CREATE INDEX idx_nodes_geom ON bavaria.nodes USING gist (geom);
2) rencana kueri terlihat seperti ini:
HashAggregate (cost=284908.49..284908.75 rows=26 width=103)
-> Nested Loop (cost=111.27..283900.80 rows=201537 width=103)
-> Bitmap Heap Scan on relpolygons relpoly (cost=4.48..102.29 rows=26 width=5886)
Recheck Cond: (tags @> '"boundary"=>"administrative", "admin_level"=>"6"'::hstore)
-> Bitmap Index Scan on relpolygons_geom_tags (cost=0.00..4.47 rows=26 width=0)
Index Cond: (tags @> '"boundary"=>"administrative", "admin_level"=>"6"'::hstore)
-> Bitmap Heap Scan on nodes node (cost=106.79..10905.50 rows=983 width=127)
Recheck Cond: (relpoly.geom && geom)
Filter: _st_intersects(relpoly.geom, geom)
-> Bitmap Index Scan on idx_nodes_geom (cost=0.00..106.55 rows=2950 width=0)
Index Cond: (relpoly.geom && geom)
3)
Saya membuat dua indeks berikut, tetapi rencana kueri (dan runtime) tidak berubah
CREATE INDEX relpolygons_tags_boundary on bavaria.relpolygons( (tags->'boundary') );
CREATE INDEX relpolygons_tags_admin on bavaria.relpolygons( (tags->'admin_level') );
ANALYZE bavaria.relpolygons;
sumber
boundary
danadmin_level
) ke dalam kolom tambahan di tabel, dan gunakan secara langsung.Jawaban:
Cara terbaik untuk mengindeks tag hstore adalah menggunakan indeks GIN atau GIST, yang dari dokumen , mendukung @>,?,? & Dan? | operator , yaitu, pencarian pada kunci dan pasangan kunci / nilai. Pendekatan Anda menggunakan fungsi untuk mengekstrak tag untuk indeks B-tree masuk akal, tetapi karena Anda juga memeriksa pasangan kunci / nilai tertentu, penganalisis telah memilih pemindaian tabel penuh.
Saya tidak memiliki akses ke bavaria.relpolygons, tetapi berdasarkan permintaan serupa untuk OSM UK tentang batas kecepatan dan tag jalan raya, saya mendapatkan ini untuk saya jelaskan pada permintaan berikut:
yang menunjukkan pemindaian indeks langsung (menggunakan indeks inti), yang untuk tabel dengan 10 juta baris cukup menggembirakan. Indeks dibuat dengan sederhana:
Meskipun saya tidak dapat memeriksa kondisi spasial Anda, saya kira ini kurang selektif
dan karena itu hanya akan digunakan untuk kondisi periksa ulang.
Ada juga jawaban SO yang luar biasa tentang perbedaan antara indeks GIN dan GIST . Temuan umum adalah bahwa indeks GIN sementara lebih besar dan lebih lambat untuk dibangun, jauh lebih cepat pada masalah pencarian teks.
Maaf untuk menjawab begitu terlambat, tetapi saya baru-baru ini melakukan pekerjaan yang serupa pada OSM dan hstore, dan menemukan bahwa saya tidak hanya pernah membintangi pertanyaan ini, tetapi sekarang saya bisa menjawabnya: D.
sumber