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