Hstoreキー/値と空間クエリの組み合わせが大きすぎるOSM抽出を処理するには遅すぎる


13

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;

1
bavaria.nodesに空間インデックスはありますか?
user30184

はい、私は質問を編集し、ノード上のインデックスとクエリプランについての情報を提供してきました
アルフKortig

3
2つのオプション。1-hstoreタグのインデックスを追加します。2-クエリに使用しているタグ(boundaryおよびadmin_level)をテーブルの追加の列に抽出し、それらを直接使用します。
BradHards

編集(3)を参照:2つのインデックスが追加されましたが、クエリプランにもランタイムにも変更はありませんでした。
アルフコルティグ

いくつかのテストの後、(3)で正しいインデックスを作成したかどうかはもうわかりません。これまでのところ、->と?のインデックスを作成できました。hstore演算子。しかし、私が使用しています@>私のクエリで
アルフKortig

回答:


5

hstoreタグにインデックスを付ける最良の方法は、ドキュメントから@>、?、?&および?|をサポートするGINまたはGISTインデックスを使用することです 演算子、つまり、キーとキー/値のペアを検索します。関数を使用してBツリーインデックスのタグを抽出するアプローチは合理的ですが、特定のキー/値のペアもチェックしているため、アナライザーは全表スキャンを選択しました。

bavaria.relpolygonsにはアクセスできませんが、速度制限と高速道路タグに関するOSM UKの同様のクエリに基づいて、次のクエリの説明でこれを取得します。

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))

これは、直接インデックススキャン(gistインデックスを使用)を示しています。これは、1,000万行のテーブルでは有望です。インデックスは次の単純なもので作成されました。

CREATE INDEX ix_ways_tags_gist ON ways USING gist (tags);

私はあなたの空間状態を確認することはできませんが、私はそれがより選択的ではないと推測しています

WHERE relpoly.tags @> '"boundary" => "administrative"、 "admin_level" => "6"' :: hstore。

したがって、再チェック条件にのみ使用されます。

GINインデックスとGISTインデックスの違いについても、この素晴らしい回答があります。一般的な発見は、GINインデックスは大きく、構築に時間がかかりますが、テキスト検索の問題でははるかに速いということです。

遅刻して申し訳ありませんが、最近OSMとhstoreで同様の作業を行っており、この質問にスターを付けただけでなく、回答できるようになりました:D。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.