PostGISを使用した最近傍計算の最適化


13

PostGISを使用して、ポリゴンの最近傍を計算しています。計算したいのは、各ポリゴンから最も近いポリゴンまでの最小距離です。

これまでのところ、マイク・トゥウズの答え(小さな変更を引用)から大きな助けを得ました。

SELECT 
  a.hgt AS a_hgt,
  b.hgt AS b_hgt,
  ST_Distance(a.the_geom, b.the_geom) AS distance_between_a_and_b
FROM 
  public."TestArea" AS a, public."TestArea" AS b
WHERE
  a.hgt !=  b.hgt AND ST_Distance(a.the_geom, b.the_geom) < 400

次に、最小値を計算しました:

SELECT a_hgt, MIN(distance_between_a_and_b)
FROM public."lon_TestArea"
GROUP BY a_hgt

ただし、私の挑戦は、多数のポリゴン(1,000,000)についてこれを計算することです。上記の計算では、各ポリゴンを他のすべてのポリゴンと比較しているので、10 ^ 12の計算を実行する必要がないように計算を改善する方法を考えました。

私が考えていたのは、各ポリゴンをバッファリングしてから、そのポリゴンのバッファ内のすべての値の最近傍を計算し、最小値を記録することでした。それが最善のアプローチであるか、PostGISに使用すべき関数があるかどうかはわかりません。


編集:ニックラスの提案のいずれかを使用して、私は実験していST_Dwithin()ます:

CREATE TABLE mytable_withinRange AS SELECT 
  a.hgt AS a_hgt,
  b.hgt AS b_hgt,
  ST_DWithin(a.the_geom, b.the_geom, 400)
FROM 
  public."lon_TestArea" AS a, public."lon_TestArea" AS b

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

これは、各ポリゴンのIDと、特定の距離内にあるかどうかのテーブルを返します。IF/ELSESQLを使用して型ステートメントを構築することは可能ですか?(CASE条件の使用について読んだ)または、作成したテーブルを元のテーブルに結合してから、ST_Distanceを使用してクエリを再度実行する必要がありますか?


私の答えのボストンgisリンクの2番目の例を見てください。クエリのwhere部分でst_dwithinを使用する必要があります。
ニックラスアベン

回答:


7

BostonGISページには、大きな「最近傍」セクションがあります


編集:

どう?

CREATE TABLE mytable_withinRange AS SELECT 
 a.hgt AS a_hgt,
 b.hgt AS b_hgt
FROM 
 public."lon_TestArea" AS a, public."lon_TestArea" AS b
WHERE 
 ST_DWithin(a.the_geom, b.the_geom, 400)

CASE文

SELECT a,
   CASE WHEN a=1 THEN 'one'
        WHEN a=2 THEN 'two'
        ELSE 'other'
   END
FROM test;

WHERE ST_DWithin(a.the_geom, b.the_geom, 400)400計算される距離以上の距離を妨げるのか、それとも記録されるのかを知っていますか?また、caseステートメントを数値計算に使用できますか?例:CASE WHEN ST_DWithin(a.the_geom, b.the_geom, 400) == TRUE THEN ST_DWithin(a.the_geom, b.the_geom)
djq

1
@celenius距離が400 mを超える場合、選択部分の何も計算されません。なぜあなたがミックスにケースを入れたいのか分かりません。
ニックラスアベン

@Nicklas OK-わかりました。400未満の距離しか保存されていなかったのではないかと思った。これにより、私よりもずっと簡単になります。ありがとう!
djq

3

ハロー

物事をより速く動かすために考慮すべきことがいくつかあり、将来可能になるかもしれないものがいくつかあります。

最初に、すべての組み合わせの計算を回避するために、バッファーを使用してある最小範囲のポリゴンを見つけることを検討していると述べました。

Boston gisの別のリンクで説明したように、PostGISでそれを行う正しい方法はST_Dwithinを使用することです。ST_Dwithinは、インデックスを使用して、特定の範囲内の近隣を検索します。

もちろん、すべてのポリゴンでst_DWithinの固定値を使用するだけで十分な場合、またはunderdarkやwildintellectが議論しているようなことを行う必要がある場合は、データセットに依存します。

2番目は、ここでPostGIS 1.5以降を使用することです。これは、境界ボックスが交差しない場合、ポリゴンからポリゴンへの計算が1.5よりもはるかに高速であるためです。詳細については、こちらご覧ください。

3番目に言及するのは未来です。

PostgreSQL 9.1にはknn-gistと呼ばれるものがあります。これは、yesまたはnoと答えるだけでなく、インデックスから直接順序付けられた結果を返すことができるインデックスです。あなたはそれについてここで読むことができます

しかし、knn gistがこのようなことを支援する前に、PostGIS側で多くの作業を行う必要があります。そのためのチケットがここにあります。

よろしく

ニクラス


Nicklasの提案に感謝します。pgAdmin / PostGISを起動して実行するのは難しいとわかったので、現時点では1.5の使用を避けると思います。ST_Dwithin()はこれを解決する方法のようです。
djq

2
1.5をインストールしても、postgresqlとpgadminの関係には影響しません。データベースサーバーに複数のバージョンのpostgisを配置してから、そのうちの1つをデータベースにロードできます。したがって、1つのデータベースサーバーに1つの1.4データベースと1つの1.5データベースを配置できます。
ニックラスアベン

1

Nathan Kerrのマスター作品に関連する以下のページは、この直接的な問題についての良い洞察を提供します。私の同僚は、ここここでBostongisの方法を試しましたが、正しく機能させるためにいくつかの問題がありました。

バッファに似ていることを考える別のアプローチは、長方形を拡大/縮小することです。基本的に1を渡すと、少なくとも1つの交差をキャッチすると思われる境界ボックス(元のポリゴンのbboxに対する直線+ x単位)が交差します。交差を取得したデータに対して、それらの一致を最も近いものとしてテストするサブクエリを実行します。一致しなかったデータについては、境界ボックスを展開して繰り返します。

これは明らかに再帰的なプログラミングの問題であり、PythonでShapelyを使用する方が、postgisで直接100%実行するよりも優れている可能性があります。

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