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;
boundary
dan admin_level
) ke dalam kolom tambahan di tabel, dan gunakan secara langsung.