Kombinasi kunci / nilai Hstore dan kueri spasial terlalu lambat untuk menangani ekstrak OSM yang lebih besar


13

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;

1
Apakah Anda memiliki indeks spasial di bavaria.nodes?
user30184

ya, saya sudah mengedit pertanyaan dan memberikan info tentang indeks pada node dan rencana kueri
Alf Kortig

3
Dua pilihan. 1 - tambahkan indeks untuk tag hstore. 2 - ekstrak tag yang Anda gunakan untuk kueri Anda ( boundarydan admin_level) ke dalam kolom tambahan di tabel, dan gunakan secara langsung.
BradHards

Lihat edit (3): dua indeks ditambahkan, tetapi tidak ada perubahan pada paket kueri atau runtime.
Alf Kortig

Setelah beberapa pengujian saya tidak yakin lagi apakah saya membuat indeks yang benar dalam (3). Sejauh ini, saya berhasil membuat indeks untuk -> dan? operator hstore. Namun, saya menggunakan @> dalam permintaan saya
Alf Kortig

Jawaban:


5

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:

SELECT count(*) 
 FROM ways 
WHERE tags @> 'highway=>motorway'::hstore 
 AND tags @> 'maxspeed=>"50 mph"'::hstore;


Aggregate  (cost=48.66..48.67 rows=1 width=0)
    ->  Index Scan using ix_ways_tags_gist on ways  (cost=0.42..48.64 rows=11 width=0)
     Index Cond: ((tags @> '"highway"=>"motorway"'::hstore) AND (tags @> '"maxspeed"=>"50 mph"'::hstore))

yang menunjukkan pemindaian indeks langsung (menggunakan indeks inti), yang untuk tabel dengan 10 juta baris cukup menggembirakan. Indeks dibuat dengan sederhana:

CREATE INDEX ix_ways_tags_gist ON ways USING gist (tags);

Meskipun saya tidak dapat memeriksa kondisi spasial Anda, saya kira ini kurang selektif

WHERE relpoly.tags @> '"batas" => "administratif", "admin_level" => "6"' :: hstore.

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.

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.