ポリゴンクエリの非常に大きなポイントを最適化する


9

住所ポイントの全国データセット(3700万)とタイプMultiPolygonZの洪水アウトライン(200万)のポリゴンデータセットがあります。一部のポリゴンは非常に複雑で、最大ST_NPointsは約200,000です。PostGIS(2.18)を使用してフラッドポリゴンにあるアドレスポイントを特定し、これらをアドレスIDとフラッドリスクの詳細を含む新しいテーブルに書き込もうとしています。アドレスの観点(ST_Within)から試してみましたが、洪水地域の観点(ST_Contains)から始めてこれを入れ替えました。根拠は、洪水のリスクのない大きな地域があることです。両方のデータセットが4326に再投影され、両方のテーブルに空間インデックスがあります。以下の私のクエリは3日間実行されており、すぐに終了する兆候はありません!

select a.id, f.risk_factor_1, f.risk_factor_2, f.risk_factor_3
into gb.addresses_with_flood_risk
from gb.flood_risk_areas f, gb.addresses a
where ST_Contains(f.the_geom, a.the_geom);

これを実行するより最適な方法はありますか?また、このタイプのクエリを長時間実行する場合、リソース使用率とpg_stat_activityを確認する以外に、進行状況を監視する最良の方法は何ですか?


私の元のクエリは3日間で問題なく終了し、他の作業に追われたため、ソリューションを試すために時間を費やす必要がなくなりました。しかし、私はこれを再検討し、推奨事項を検討したところ、これまでのところ良好です。私は以下を使用しました:

  1. ここで提案されているST_FishNetソリューションを使用して、英国上空に50 kmのグリッドを作成しました
  2. 生成されたグリッドのSRIDをBritish National Gridに設定し、それに空間インデックスを構築しました
  3. ST_IntersectionとST_Intersectsを使用してフラッドデータ(MultiPolygon)をクリップしました(ここで問題になるのは、shape2pgsqlがZインデックスを追加したときに、gemでST_Force_2Dを使用する必要があったことだけです)
  4. 同じグリッドを使用してポイントデータをクリップしました
  5. 行に作成されたインデックス、各テーブルにcolと空間インデックス

これでスクリプトを実行する準備ができました。国全体をカバーするまで、結果を新しいテーブルに移入する行と列を繰り返し処理します。しかし、洪水データを確認したところ、非常に大きなポリゴンのいくつかが翻訳中に失われたようです!これは私のクエリです:

SELECT g.row, g.col, f.gid, f.objectid, f.prob_4band, ST_Intersection(ST_Force_2D(f.geom), g.geom) AS geom 
INTO rofrse.tmp_flood_risk_grid 
FROM rofrse.raw_flood_risk f, rofrse.gb_grid g
WHERE (ST_Intersects(ST_Force_2D(f.geom), g.geom));

私の元のデータは次のようになります:

元の洪水データ

ただし、ポストクリッピングは次のようになります。

グリッド化された洪水データ

これは、「欠けている」ポリゴンの例です。

「欠落」ポリゴン


ソウルのFOSS4Gで会ったことに気づき、ESRIロケーターハブの不思議について話しました:-)
John Powell

分割統治のアプローチを終えたことはありますか?このアプローチでベンチマーク時間を更新できますか?
アンドリュー、

回答:


6

最後の質問に最初に答えるには、この投稿を参照してくださいクエリの進行状況を監視できることが望ましいことについて。この問題は困難であり、空間クエリで複雑になります。これは、基盤となるテーブルスキャン実装のループカウンターから取得できるフラッドポリゴンの包含について、アドレスの99%がすでにスキャンされていることがわかっているためです。最後の1%のアドレスが最も多くのポイントでフラッドポリゴンと交差し、前の99%がいくつかの小さなエリアと交差する場合に役立ちます。これは、EXPLAINがスキャンされる行の指標を提供するため、空間的に役に立たないことがある理由の1つですが、明白な理由により、ポリゴンの複雑さ(したがって、大きな比率)を考慮していません実行時間の)交差/交差タイプのクエリ。

2番目の問題は、次のようなものを見ると

EXPLAIN 
SELECT COUNT(a.id) 
FROM sometable a, someothertable b
WHERE ST_Intersects (a.geom, b.geom)

多くの詳細を見逃した後、次のようなものが表示されます。

_st_intersects(a.geom, b.geom)
   ->  Bitmap Index Scan on ix_spatial_index_name  (cost...rows...width...))
   Index Cond: (a.geom && geom)

最後の条件&&は、実際のジオメトリのより正確な交差を行う前に、境界ボックスチェックを行うことを意味します。これは明らかに賢明であり、Rツリーの動作の中心にあります。ただし、私は過去に英国の洪水データにも取り組んだことがあるので、(マルチ)ポリゴンが非常に広範囲である場合、データの構造に精通しています-この問題は、河川が45度に流れている場合などに特に深刻です度-巨大な境界ボックスが表示され、非常に複雑なポリゴンで膨大な数の潜在的な交差がチェックされる可能性があります。

「クエリが3日間実行されており、1%と99%のどちらであるかわからない」という問題に対して私が思いついた唯一の解決策は、ダミーに対して一種の分割統治を使用することですつまり、plpgsqlのループで、またはコンソールで明示的に、領域を小さなチャンクに分割し、それらを個別に実行します。これには、複雑なポリゴンをパーツにカットするという利点があります。つまり、ポリゴンチェックの後続のポイントが小さなポリゴンで機能し、ポリゴンのバウンディングボックスがはるかに小さくなります。

英国全体で1週間以上実行されていたクエリを強制終了した後、英国を50 km x 50 kmのブロックに分割することで、なんとかクエリを実行できました。余談ですが、上記のクエリが単なるSELECTではなくCREATE TABLEまたはUPDATEであることを願っています。フラッドポリゴン内にあることに基づいて1つのテーブル(アドレス)を更新する場合、いずれにしても、更新されるテーブル全体をスキャンする必要があるため、実際に空間インデックスを作成してもまったく役に立ちません。

編集:画像が千の言葉の価値があるということに基づいて、ここにいくつかの英国の洪水のデータの画像があります。非常に大きなマルチポリゴンが1つあり、そのバウンディングボックスがその領域全体をカバーしているため、たとえば、最初に洪水ポリゴンと赤いグリッドを交差させると、南西隅の正方形が突然テストされるだけであることが簡単にわかります。ポリゴンの小さなサブセットに対して。

ここに画像の説明を入力してください


こんにちはジョン、包括的な答えをありがとうございます。グリッドアプローチに関する推奨に従います。非常に賢明な提案のように聞こえます。単純化して正確さを失いたくありません。私は1つのブロックでベンチマークを行ってから、並列実行します。最近のクラウドの方がずっと簡単です!ありがとうございました
Mark Varley

こんにちはマーク、心配ありません。役に立ったと思われる場合は、回答を受け入れることを検討してください。これは、サイトをクリーンに保つのに役立ちます。回答が受け入れられない質問は、Stack Exchangeサイトが見る指標の1つです。
John Powell

了解しました。これが私の最初の投稿です。通常、詳細なスレッドと役立つ応答から回答を見つけます。クエリは約3日後に今朝最後に終了しましたが、それほど悪くはありませんが、今日のアドバイスに従い、パフォーマンスを向上させるためにチャンクに分割します。助けてくれてありがとうジョン、そしておそらく8月にボンでお会いしましょう!
Mark Varley 2016年

写真を追加しましたが、あなたは写真:Dを持っていることに気づきましたが、他の人が私が何をしているかを視覚化するのに役立つかもしれません。はい、ほぼ間違いなくFoss4G UKに行く予定で、ボンについて考えます。
John Powell
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.