PostgreSQL 9.3.5およびPostGIS 2.1.4を使用して、OSMデータの統計を計算しようとしています。Geofabrikからダウンロードした小さなバイエルン抽出物から始めました。dbスキーマは通常のAPI 0.6スキーマであり、データはダンプアプローチを介してPostgresにインポートされました(osmosisに付属のpgsnapshot_schema_0.6 * .sqlスクリプトを使用)。ANALYZE VACUUMも実行されました。
私が使用している唯一のカスタムメイドのものは、すべての管理境界関係のマルチポリゴンを含むポリゴンテーブルです。ポリゴンジオメトリは、決して簡素化されていません。
私が今達成しようとしているのは、バイエルンのadmin = 6境界内にあるすべてのノードをカウントすることです。これが私のSQLクエリです。
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;
Postgresはネストされたループ結合を行っており、admin = 6境界ごとにすべてのノードをスキャンするため、このクエリの実行時間はひどいです。参考までに、バイエルンは98個のadmin = 6ポリゴンに分割され、バイエルン抽出物には約3,000万個のノードがあります。
この準最適なクエリの実行を回避し、Postgresにすべてのノードを一度だけスキャンするように指示することは可能ですか(たとえば、結果セット内の対応するポリゴンのカウンターをインクリメントするか、ヒントを使用して)
編集:
1)バイエルンノードに空間インデックスが存在する:
CREATE INDEX idx_nodes_geom ON bavaria.nodes USING gist (geom);
2)クエリプランは次のようになります。
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)
次の2つのインデックスを作成しましたが、クエリプラン(およびランタイム)は変更されませんでした
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
およびadmin_level
)をテーブルの追加の列に抽出し、それらを直接使用します。