<-> — 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)