<-> — 返回 A 和 B 之间的 2D 距离。
double precision <->(
geometry A , geometry B )
;
double precision <->(
geography A , geography B )
;
<->
运算符返回两个几何图形之间的 2D 距离。在 "ORDER BY" 子句中使用时,可提供索引辅助的最近邻结果集。对于低于 9.5 版本的 PostgreSQL,仅给出边界框的质心距离;对于 9.5 及更高版本的 PostgreSQL,则进行真正的 KNN 距离搜索,给出几何图形之间的真实距离,以及地理的距离球面。
此操作数将利用几何图形上可能存在的 2D GiST 索引。它与使用空间索引的其他运算符不同,空间索引仅在运算符位于 ORDER BY 子句中时才使用。 |
仅当其中一个几何图形是常量(不在子查询/cte 中)时,索引才会生效。例如:'SRID=3005;POINT(1011102 450541)'::geometry,而不是 a.geom |
有关详细示例,请参阅 PostGIS 工作坊:最近邻搜索。
增强功能:2.2.0 -- 为 PostgreSQL 9.5+ 的几何和地理提供真正的 KNN(“K 最近邻”)行为。请注意,地理 KNN 基于球体而不是椭球体。对于 PostgreSQL 9.4 及更低版本,地理支持是新增的,但仅支持质心框。
已更改:2.2.0 -- 对于 PostgreSQL 9.5 用户,旧的混合语法可能会更慢,因此,如果你的代码仅在 PostGIS 2.2+ 9.5+ 上运行,则需要删除该 hack。请参见以下示例。
可用性:2.0.0 -- 弱 KNN 基于几何质心距离而不是真实距离提供最近邻。点类型的结果精确,所有其他类型的结果不精确。适用于 PostgreSQL 9.1+。
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",你将看到第二个查询的性能有所提高。
对于使用 PostgreSQL < 9.5 的用户,请使用混合查询来查找真正的最近邻。首先使用索引辅助的 KNN 进行 CTE 查询,然后进行精确查询以获得正确的排序
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)