GISTインデックスを使用したPostgis 2.0の最近傍の問題(<->関数)


25

テーブル(cosn1)の各行について、同じクラスの最も近いポリゴンまでの距離を計算するために、Postgis 2.0の新しい関数<->(ジオメトリ距離重心)を使用しようとしています。

私は次のコードを使用しようとしました:

WITH index_query AS (
  SELECT g1.gid As ref_gid, ST_Distance(g1.the_geom,g2.the_geom) As ENN    
    FROM "cosn1" As g1, "cosn1" As g2   
    WHERE g1.gid <> g2.gid AND g1.class = g2.class
    ORDER BY g1.gid, g1.the_geom <-> g2.the_geom) 
SELECT DISTINCT ON (ref_gid) ref_gid, ENN 
    FROM index_query
ORDER BY ref_gid, ENN;

しかし、私は警告を実現します:

注:インデックスは、ジオメトリの1つが定数(サブクエリ/ cteではない)である場合にのみ有効です。例: 'SRID = 3005; POINT(1011102 450541)' :: geometryではなくa.geom

つまり、インデックスはまったく使用されず、クエリは使用前とほぼ同じ時間がかかります:

SELECT DISTINCT ON(g1.gid)  g1.gid As ref_gid, ST_Distance(g1.the_geom,g2.the_geom) As ENN    
    FROM "cosn1" As g1, "cosn1" As g2   
    WHERE g1.gid <> g2.gid AND g1.class = g2.class
    ORDER BY g1.gid, ST_Distance(g1.the_geom,g2.the_geom)

誰かが私のクエリのパフォーマンスを改善できる回避策を教えてもらえますか?

どうもありがとうございました。


まだ回答がない場合は、PostGISメーリングリストでこれを聞いてください。
GISジョナサン

私はすでにやったが、何の反応もなかった。
アレクサンドルネトー

3
where句でg1.gid> g2.gidを使用できます。これにより、実行する必要がある距離計算の数が減ります。残念ながら、定数なしで<->演算子が動作するまで、この種のクエリの速度はそれほど向上しません。
ジョンパウエル

ジョン、「cosn1」テーブルの各ポリゴンのEENを更新する必要があるために繰り返されるものも含め、すべてのgidを保持する必要があります。しかし、あなたが言ったことは私にアイデアを与えました。あなたが言うように、距離の計算を減らすためにg1.gid> g2.gisを使用しますが、結果にg1.gidとg2.gidを保持します。その後、2つのサブクエリ(gidとしてg1.gisを使用するものとg2.gidを使用するもの)を結合できます。ありがとう
アレクサンドル・ネト

一定の問題を回避する可能な解決策は、the_geomをパラメーターとして使用して、SQL関数内で<->を使用することであることがわかりました。いくつかのテストを行いましたが、場合によってははるかに高速です()。しかし、私の場合、距離は同じテーブル内にあるため、プロセス中に多くの距離計算が繰り返され、直接クエリを使用するよりも遅くなります。
アレクサンドルネトー

回答:


2

この演算子<->が正常に動作していないように聞こえます。これがバグかどうかはわかりませんが、ジオメトリがオーバーラップしていないため距離がゼロであると報告されました。興味ない?

さて、公正な従来のSQLクエリの最適化はどうですか?<->演算子を使用するとこれらの予期しない結果になるため、st_centroidに置き換えます。速度が大幅に向上しました。

st_overlapsのセマンティクスが同じことを望みます。少なくともこれは<->に関するドキュメントから理解できました

Postigsのドキュメントから<->

他のジオメトリタイプの場合、浮動小数点バウンディングボックスの重心間の距離が返されます。

〜5.5kポリゴンのテストデータでは、空間インデックスを作成せずに、〜1000秒から〜5秒にスピードアップしました。

とにかく、DISTINCT ONを使用してグループ化を行うのはなぜですか?一部の人々はそれを使用していますが、重複を排除するためにgroup byが存在していませんか?

st_centroidエラーが導入されていない標準SQL最適化を使用したクエリ

select g1.gid, min( st_distance( g1.the_geom, g2.the_geom ) ) AS enn
FROM 
  "cosn1" AS g1, "cosn1" AS g2
WHERE
  g1.gid <> g2.gid
  AND g1.class = g2.class
  AND g1.the_geom && g2.the_geom
GROUP BY
  g1.gid

楽しいクリスマス休暇!


申し訳ありませんが、あなたの答えは問題を解決しません。実際にははるかに高速ですが、最終結果は実際のジオメトリではなくポリゴンの重心を使用して計算されるため、結果は正確ではありません。<->は、最近傍への候補の検索を最適化することを目的としていますが、最終的には実際のジオメトリを使用して最適な候補までの距離を計算する必要があります。また、DISTINCT ON \ ORDER BYの代わりにMIN \ GROUP BYを使用しようとしましたが、速度が遅いようです。
アレクサンドル・ネト

しかし、演算子<->のpostgisマニュアルでは、非ポイントジオメトリに重心を使用していると記載されています。したがって、私のソリューションでは同様の結果が得られます。上位のクエリと同じ結果が得られます。演算子<->を使用した結果も正しいことを確認してください。テストデータの長さが0であると報告されたため、結果が破損する可能性があり、このソリューションではより正確なデータが提供されました。エラーを示すサンプルレコードを一部のpastieサイトで投稿できる場合、ソリューションの欠陥を発見できます。
カビラ

クエリをチェックすると、<->演算子は候補の順序付けにのみ使用され、最終結果は実際のジオメトリを使用して計算されます。とにかく、前に言ったように、<->パフォーマンスブーストは固定小数点でのみ機能します。それが私の最初の質問でした。
アレクサンドルネト

それで、トップクエリがボトムクエリと同等ではないことに同意しますか?演算子<->はst_centroidをORDER BYし、st_distanceは異なる値を与えるため、順序が変わるのですか?別の順序では、DISTINCT ON句を渡す最初の行として別のクエリを使用できますか?有効なクエリは、速度の改善が必要な一番下のクエリですか?
カビラ

はい、最初のクエリは、一番下のクエリの速度を改善することを目的としています。はい、g1.geom <-> g2.geomは重心を使用するため、結果が少し異なる場合があります。これは、最初の行が近くにない可能性があることを意味します。それを機能させるためには、order by句にlimit 10と言う制限を設定し、距離の実際の値を抽出する必要があると思います。重心の代わりに境界ボックスを使用する<#>を使用することもできます。
アレクサンドルネト
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.