名前

<-> — A と B の 2次元距離を返します。

概要

double precision <->( geometry A , geometry B );

double precision <->( geography A , geography B );

説明

<->演算子は二つのジオメトリーの 2次元距離を返します。"ORDER BY"句内で使われ、インデックスの援助を受けた近傍結果集合の結果を返します。ジオメトリーではデカルト距離を使い、ジオグラフィでは球面上の距離を計算します。

[注記]

これのオペランドはジオメトリーで利用できるインデックスを使用します。他の演算子との相違点は、ORDER BY 句でのみインデックスが使用される点です。

[注記]

ジオメトリーのひとつが定数となる (副問い合わせ/共通テーブル式にない) 場合 (a.geom でなく'SRID=3005;POINT(1011102 450541)'::geometry 等となる場合) には、インデックスが有効になるだけです。

詳細な例についてはOpenGeo workshop: Nearest-Neighbour Searchingを参照して下さい。

Enhanced: 2.2.0 -- 真の KNN (k 近傍法) のジオメトリーとジオグラフィーの振舞い。ジオグラフィーの KNN は回転楕円体でなく球面に基づきます。

Changed: 2.2.0 -- 真の KNN が有効になると、古いハイブリッド法による回避策は遅くなることがあります。下の例を見てください。

Availability: 2.0.0 -- 弱い KNN によって、実際の距離の代わりにジオメトリーの重心に基づく近傍が得られます。ポイントは確実な結果を得て、他のタイプは全て不確実な結果を得ます。

コード
SELECT ST_Distance(geom, 'SRID=3005;POINT(1011102 450541)'::geometry) as d, edabbr, vaabbr
FROM va2005
ORDER BY d limit 10;
出力
d         | edabbr | vaabbr
------------------+--------+--------
                0 | ALQ    | 128
 5541.57712511724 | ALQ    | 129A
 5579.67450712005 | ALQ    | 001
  6083.4207708641 | ALQ    | 131
  7691.2205404848 | ALQ    | 003
 7900.75451037313 | ALQ    | 122
 8694.20710669982 | ALQ    | 129B
 9564.24289057111 | ALQ    | 130
  12089.665931705 | ALQ    | 127
 18472.5531479404 | ALQ    | 002
(10 rows)

KNN の生の答は次のとおりです。

コード
SELECT ST_Distance(geom, 'SRID=3005;POINT(1011102 450541)'::geometry) as d,edabbr, vaabbr
FROM va2005
ORDER BY geom <-> 'SRID=3005;POINT(1011102 450541)'::geometry limit 10;
出力
        d         | edabbr | vaabbr
------------------+--------+--------
                0 | ALQ    | 128
 5541.57712511724 | ALQ    | 129A
 5579.67450712005 | ALQ    | 001
  6083.4207708641 | ALQ    | 131
  7691.2205404848 | ALQ    | 003
 7900.75451037313 | ALQ    | 122
 8694.20710669982 | ALQ    | 129B
 9564.24289057111 | ALQ    | 130
  12089.665931705 | ALQ    | 127
 18472.5531479404 | ALQ    | 002
(10 rows)

二つのクエリで"EXPLAIN ANALYZE"を実行すると、二つ目で速度が改善したことが分かります。

プランで直接確実な距離を生成できない時には、真の近傍を見つけるには複合クエリーを追加居ます。まずインデックスを使った KNN による CTE (Common Table Expression, WITH 句) クエリーを実行し、その後に正しい順序を得るための確実なクエリーを実施します。次のようにします:

コード
WITH index_query AS (
  SELECT ST_Distance(geom, 'SRID=3005;POINT(1011102 450541)'::geometry) as d,edabbr, vaabbr
    FROM va2005
  ORDER BY geom <-> 'SRID=3005;POINT(1011102 450541)'::geometry LIMIT 100)
  SELECT *
    FROM index_query
  ORDER BY d limit 10;
出力
        d         | edabbr | vaabbr
------------------+--------+--------
                0 | ALQ    | 128
 5541.57712511724 | ALQ    | 129A
 5579.67450712005 | ALQ    | 001
  6083.4207708641 | ALQ    | 131
  7691.2205404848 | ALQ    | 003
 7900.75451037313 | ALQ    | 122
 8694.20710669982 | ALQ    | 129B
 9564.24289057111 | ALQ    | 130
  12089.665931705 | ALQ    | 127
 18472.5531479404 | ALQ    | 002
(10 rows)

関連情報

ST_DWithin, ST_Distance, <#>