PostGIS ST_Intersectsのパフォーマンスの問題を修正する方法は?


9

私はpostgisの初心者で、クエリのパフォーマンスに問題があります。

この私のクエリ:

SELECT DISTINCT ON (userid) userid ,ST_AsText(position), timestamp  
FROM table1 
WHERE ST_Intersects ( ST_GeomFromText('a multiypolygon geom goes here',4326),position) 
ORDER BY userid, timestamp desc

問題は、私のマルチポリゴンに非常に大きなポリゴン(単語のドキュメントでは600ページの長さです)が含まれていて、実行に2時間以上かかったことです。

クエリを最適化する方法または別の方法を使用する方法はありますか?

どうぞよろしくお願いします!

回答:


8

すべきことは、大きなマルチポリゴンをテーブルに(ST_Dumpを使用して)単一のポリゴンとしてテーブルに配置し、インデックスを配置することです。何かのようなもの:

CREATE TABLE big_polygon as
SELECT (ST_Dump( ST_GeomFromText('a multiypolygon geom goes here',4326))).geom as geom;

-- It is always great to put a primary key on the table
ALTER table big_polygon ADD Column gid serial PRIMARY KEY;

-- Create the index
CREATE INDEX idx_big_polygon_geom
on big_polygon
USING gist(geom);

-- To give the database some information about how the index looks
analyze big_polygon;

-- Then you go:
SELECT DISTINCT ON (userid) userid ,ST_AsText(position), timestamp  
FROM table1, big polygon WHERE ST_Intersects ( big_polygon.geom,position) 
ORDER BY userid, timestamp desc;

いくつかの理由から、それはずっと速いはずです。


このすばらしい返事をしてくれたNicklasに感謝します。申し訳ありませんが、複数のポリゴンがあり、それらはすでにインデックス付きのテーブルに格納されていることを忘れてしまいました。しかし、geomデータを直接提供する方が高速になると考えました。しかし、私はあなたが提案する方法を試みますが、それでも非常に長い時間がかかります!他の提案?
サラ

@サラ 。OK、ST_Dumpで提案したように、マルチジオメトリを単一のジオメトリに分割しようとしましたか?
NicklasAvén

何人のユーザーのポジションについて話しているのですか?大きなポリゴンはいくつありますか?あなたはbig_polygons_tableからSELECT ST_npoints(geom)から何を取得しますか?
NicklasAvén

申し訳ありませんが、わかりやすくするためにテーブルについて詳しく説明します。table1には、約230行のgeom列が含まれており、各行にマルチポリゴンがあります(国を表すため、サイズが異なります)。 、the_geom colにインデックスがあります。位置列(ポイント)、タイムスタンプ、ユーザーID、ID(pk)、および(位置、タイムスタンプ、ユーザーID)を使用して作成された3つのインデックスを含むTable2。このテーブルは非常に大きく、103496003行あります。 16.混乱させてすみませんが、本当にあなたの助けが必要です!おかげで
サラ

2

それは、どのような品質-必要な精度に依存します。次を使用することにより、明らかにポリゴンを単純化できます:http : //postgis.net/docs/ST_Simplify.html

GISアプリケーションの開発中によく行ったことは、データを最小限に抑えるための最良の方法を考えることでした。例えば。たとえば、境界ボックス内のポリゴンを事前選択します。-ズームレベルによっては、非常に正確な結果(st_simplify)は必要ありません...

少しお役に立てば幸いです。


迅速な対応にマーティンに感謝します。私の問題は、結果を非常に正確にする必要があるため、この関数はここでは役に立たないと思います!しかし提案をありがとう
サラ

0

postgresやsqlの専門知識に応じて、いくつかのオプションがあります。

  1. EXPLAINコマンドを使用してクエリを分析し、特定のボトルネックが発生しているかどうかを確認します。警告:EXPLAINの出力が理解しにくい場合があります

  2. table1のジオメトリの大部分またはかなりの部分がマルチポリゴンと交差しないと予想される場合は、より単純なポリゴンに対して予備条件を適用して(つまり、マルチポリゴンを小さな部分に分割することにより)、重いマルチポリゴンの交差を次のものだけで実行することができます。それらの結果。例については、以下を参照してください。

  3. CPUがボトルネックである場合(つまり、サーバーがコンピューティングの交差部分でスタックしている場合)、大きくて高速で強力なCPUを入手するか、AmazonのEC2から1回限りの高CPUインスタンスをレンタルし、それを破棄することをお勧めします終わった

アイテム2のクエリ例:

SELECT DISTINCT ON (st1.userid) st1.userid ,ST_AsText(st1.position), st1.timestamp  
FROM (
    select userid, position, timestamp from table1 
    WHERE ST_Intersects ( YOUR_MULTIPOL_BOUNDS_HERE,position)
) as st1 
WHERE ST_Intersects ( ST_GeomFromText('a multiypolygon geom goes     here',4326),st1.position) 
ORDER BY st1.userid, st1.timestamp desc

パフォーマンスを改善するために、副選択st1を一時的にテーブルとして実体化して、インデックスを付けることができます。

@Nicklasは、提案2の例が役に立たないはずであるとコメントで指摘するのは正しいことです。彼は正しいですが、私も(部分的に)正しいと思います。

実際、非常によく似た質問が、昨年11月のpostgis MLで尋ねられた(そして答えられた)ようです。

http://postgis.refractions.net/pipermail/postgis-users/2011-November/031344.html

また、単純な境界チェックによってトリガーされる偽の交差をインデックスが最も効果的に除外できるように、実際にはポリゴンを分割することが提案されていることがわかりました。


提案2は、インデックスが行っていることとまったく同じなので、役に立ちません。したがって、その構造はもう一度同じことをするだけです。
NicklasAvén12年

NicklasAvénあなたしている右の@、私は答え改正
unicoletti

0

使用する ST_SubDivide()

Postgisのバージョン2.2では、を使用できますST_SubDivide

ST_Subdivide —セット内のジオメトリが指定された数を超える頂点を持たないジオメトリのセットを返します。

setof geometry ST_Subdivide(geometry geom, integer max_vertices=256);

あなたできます

  • 一時テーブルを使用する
  • インデックス

ここではST_SubDivide、ポリゴンを頂点が10個以下のサブポリゴンに分割するために使用します。

CREATE TEMP TABLE divided AS
SELECT ST_SubDivide(bigmultipolygon,10)::geometery AS t(geom);

CREATE INDEX divided_idx ON divided USING gist(geom);

その後

SELECT DISTINCT ON (userid) userid ,ST_AsText(position), timestamp  
FROM table1
JOIN divided AS d
  ON ST_Intersects( d.geom, position )
ORDER BY userid, timestamp desc;

上記を行わないでください。丸め誤差が発生します

一般的なチューニング

また、ドキュメントの「パフォーマンスのヒント」というセクションもご覧ください。適切に調整されていることを確認してください。max_parallel_workers_per_gather並列化を利用するためにレイズを検討してください(現在デフォルトではオフになっています)。

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