15

PostGIS で次の Nearest Neighbor Query を使用しています。

SELECT g1.gid g2.gid FROM points as g1, polygons g2   
WHERE g1.gid <> g2.gid
ORDER BY g1.gid, ST_Distance(g1.the_geom,g2.the_geom)
LIMIT k;

これで、両方のテーブルの the_geom と gid 列にインデックスを作成したので、このクエリは、2 つのテーブル間の空間結合を含む他の空間クエリよりもはるかに時間がかかります。

K最近傍を見つけるより良い方法はありますか? PostGISを使用しています。

また、ジオメトリ列にインデックスを作成しているにもかかわらず、異常に時間がかかる別のクエリは次のとおりです。

select g1.gid , g2.gid from polygons as g1 , polygons as g2
where st_area(g1.the_geom) > st_area(g2.the_geom) ;

これらのクエリは Gist インデックスの恩恵を受けていないと思いますが、なぜでしょうか?

一方、このクエリは次のとおりです。

select a.polyid , sum(length(b.the_geom)) from polygon as a , roads as b  
where st_intersects(a.the_geom , b.the_geom);

ポリゴンまたはポイント テーブルよりもはるかに大きく、より複雑な空間演算子を含む「道路」テーブルが含まれているにもかかわらず、しばらくして結果を返します。

4

5 に答える 5

19

2011年9月下旬以降、PostGISは、ORDERBY句で使用可能な特別な演算子を介してインデックス付きの最近傍クエリをサポートしています。

SELECT name, gid
FROM geonames
ORDER BY geom <-> st_setsrid(st_makepoint(-90,40),4326)
LIMIT 10;

...スケーラブルな方法でgeom最も近い10個のオブジェクトを返します。-90,40いくつかの詳細(オプションと警告)はその発表の投稿にあり、<-><#>演算子の使用も公式のPostGIS2.0リファレンスに文書化されています。(2つの主な違いは<->、形状の図心を<#>比較し、それらの境界を比較することです。ポイントの違いはありません。他の形状は、クエリに適したものを選択します。)

于 2012-07-13T23:11:14.843 に答える
9

あなたの問題についてのほんの少しの考え:

st_distanceとst_areaはインデックスを使用できません。これは、両方の関数を「aはbの範囲内ですか?」のような質問に還元できないためです。または「aとbは重なっていますか?」さらに具体的に言うと、GISTインデックスは、2つのオブジェクトのバウンディングボックスでのみ機能します。

これに関する詳細については、 postgisマニュアルを参照してください。このマニュアルには、st_distanceの例と、クエリを改善してパフォーマンスを向上させる方法が記載されています。

ただし、これはk最近傍問題を解決しません。そのため、現時点では、クエリのパフォーマンスを向上させる方法がわかりません。私が見る唯一のチャンスは、k最近傍が常にxメートル未満の距離にあると仮定することです。次に、postgisマニュアルで行われているのと同様のアプローチを使用できます。

2番目のクエリは少しスピードアップする可能性があります。現在、テーブルに行があるのと同じ頻度で、テーブル1の各オブジェクトの面積を計算します。戦略は、最初にデータを結合し、次にその関数に基づいて選択することです。面積を事前計算することで、面積計算の数を大幅に減らすことができます。

WITH polygonareas AS (
    SELECT gid, the_geom, st_area(the_geom) AS area
    FROM polygons
)
SELECT g1.gid, g2.gid
FROM polygonareas as g1 , polygonareas as g2 
WHERE g1.area > g2.area;

3番目のクエリは、バウンディングボックスを使用して大幅に最適化できます。2つのオブジェクトのバウンディングボックスが重なっていない場合、オブジェクトが重なる方法はありません。これにより、特定のインデックスを使用できるため、パフォーマンスが大幅に向上します。

于 2012-05-05T12:11:49.550 に答える
5

KNNインデックスとラテラルジョインでできます。

SELECT v.gid, v2.gid,st_distance(v.the_geom, v2.the_geom)
  FROM geonames v, 
       lateral(select * 
                 from geonames v2
                where v2.id<>v.id
                ORDER BY v.the_geom <-> v2.the_geom LIMIT 10) v2
where v.gid in (...) - or other filtering condition
于 2018-09-06T14:54:22.497 に答える
0

p 個のポイントと g 個のポリゴンがあると仮定すると、元のクエリは次のようになります。

SELECT g1.gid, g2.gid FROM points as g1, polygons g2   
WHERE g1.gid <> g2.gid
ORDER BY g1.gid, ST_Distance(g1.the_geom,g2.the_geom)
LIMIT k;

pxg セット内の k 個の最近傍を返します。クエリはインデックスを使用している可能性がありますが、距離が最小の k 行を見つけるために pxg セット全体を並べ替える必要があります。代わりに必要なのは次のとおりです。

SELECT g1.gid, 
      (SELECT g2.gid FROM polygons g2   
       --prevents you from finding every nearest neighbour twice
       WHERE g1.gid < g2.gid 
       --ORDER BY gid is erroneous if you want to limit by the distance
       ORDER BY ST_Distance(g1.the_geom,g2.the_geom)
       LIMIT k)
FROM points as g1;
于 2015-01-08T20:48:12.440 に答える