简体   繁体   English

PostgreSQL - 计算两点之间的最小距离

[英]PostgreSQL - Calculate the minimum distance between two points

I have a fairly substantial point layer (just over 1 million), and I would like to select the shortest distance separating each point from this same layer to another (nearest neighbor).我有一个相当大的点层(刚刚超过 100 万),我想 select 将每个点从同一层到另一个(最近的邻居)的最短距离。 After some research on the internet, I turned to the Cross Join Lateral clause.在互联网上进行了一些研究后,我转向了交叉连接横向条款。

However, the request never ends (more than 5 hours without finalization).但是,请求永远不会结束(超过 5 小时未完成)。 I compared with the QGis Distance Matrix, and there the computation time seems to be much faster (around 10% every 5 minutes).我与 QGis 距离矩阵进行了比较,计算时间似乎要快得多(每 5 分钟大约 10%)。 I tell myself that the cause may lie in the poorly formulated request.我告诉自己,原因可能在于措辞不当的要求。

Here is the code i used:这是我使用的代码:

with couche_points as (select * from public.centroides_batis_all)
select p.id, t.id_2, t.dist
from couche_points p cross join lateral(
select r.id as id_2, p.geom <-> r.geom as dist
from couche_points r
where p.id <> r.id
order by p.geom <-> r.geom
limit 1) as t

However, everything looks good to me.但是,在我看来,一切都很好。 Is there a difference in performance between PostGis and QGis? PostGis 和 QGis 之间的性能有区别吗?

Thank you.谢谢你。

What is the point of the dummy CTE?虚拟 CTE 的意义何在? All it does is defeat the usage of any index on the real table (which is surely ample explanation for the slowness)它所做的只是破坏了真实表上任何索引的使用(这肯定是对缓慢的充分解释)

select p.id, t.id_2, t.dist
from centroides_batis_all p cross join lateral(
select r.id as id_2, p.geom <-> r.geom as dist
from centroides_batis_all r
where p.id <> r.id
order by p.geom <-> r.geom
limit 1) as t;

As I can see you are building matrix like this in your query:如我所见,您正在查询中构建这样的矩阵:

   p1  p2  p3  p4  ... pn
p1 --- d21 d31 d41 ... dn1
p2 d12 --- d32 d42 ... dn2
p3 d13 d23 --- d43 ... dn3
p4 d14 d24 d34 --- ... dn4
..........................
pn d1n d2n d3n d4n ... ---

but actually you need only half of it because left bottom half just duplicates top right half with points swapping:但实际上你只需要它的一半,因为左下半部分只是重复右上半部分并交换点:

   p1  p2  p3  p4  ... pn
p1 --- d21 d31 d41 ... dn1
p2 --- --- d32 d42 ... dn2
p3 --- --- --- d43 ... dn3
p4 --- --- --- --- ... dn4
..........................
pn --- --- --- --- ... ---
select t1.id as id, t2.id as id_2, t2.dist
from
  centroides_batis_all as t1 cross join lateral (
    select t2.id, t1.geom <-> t2.geom as dist
    from centroides_batis_all as t2 where t1.id < t2.id -- the main difference here
    order by dist limit 1) as t2;

This query will return pairs such as p1-p2 but not p2-p1 (with same distance of course)此查询将返回诸如 p1-p2 之类的对,但不返回 p2-p1 (当然具有相同的距离)

To fix this you could just duplicate rows from the previous query with swapped points:要解决此问题,您可以使用交换点复制上一个查询中的行:

with cte as (
  select t1.id as id, t2.id as id_2, t2.dist
  from
    centroides_batis_all as t1 cross join lateral (
      select t2.id, t1.geom <-> t2.geom as dist
      from centroides_batis_all as t2 where t1.id < t2.id
      order by dist limit 1) as t2)
select
  case t.n when 1 then cte.id else cte.id_2 end as id,
  case t.n when 1 then cte.id_2 else cte.id end as id_2,
  cte.dist
from cte, (values(1), (2)) as t(n);

Maybe you have got the option to split your points in four areas.也许您可以选择将您的观点分为四个方面。

1 Distance Matrix with 1.000.000 Points needs 1.000.000 x 1.000.000 = 1.000.000.000.000 calculations. 1 个具有 1.000.000 点的距离矩阵需要 1.000.000 x 1.000.000 = 1.000.000.000.000 次计算。

4 Distance MAtrix with 250.000 Points needs 250.000 x 250.000 = 250.000.000.0000 calculations. 4 具有 250.000 点的距离矩阵需要 250.000 x 250.000 = 250.000.000.0000 次计算。

Thats just 1/4 of calculations.这只是计算的 1/4。 Of Course you have to show how to handle where the spliited areas come together, but it seems to be much quicker.当然,您必须展示如何处理分割区域的组合,但它似乎要快得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 PostgreSQL 在不使用 PostGIS 的情况下计算两点之间的距离 - PostgreSQL calculate distance between two points without using PostGIS 通过PostgreSQL / PostGIS请求获取两点之间的公制距离 - Get metric distance between two points via a PostgreSQL/PostGIS request 计算2点之间的距离(大约) - Calculate distance between 2 points (approximately) Postgis计算点之间的距离 - Postgis calculate the distance between points 试图计算 PostgreSQL 中两个经纬度点之间的距离 - PostgreSQL earth_box(ll_to_earth) 返回值的单位是什么? - Trying to calculate distance between two lat-lng points in PostgreSQL - what is the unit of PostgreSQL earth_box(ll_to_earth) return value? PostgreSQL表中存储的2点之间的距离 - PostgreSQL distance between 2 points stored in table 使用带有EF Core的NetTopologySuite和postgis计算两点之间的地理距离 - Calculate the geographic distance between two points using NetTopologySuite with EF Core and postgis 在PostGIS中哪一个是计算两点之间距离的最准确方法? - In PostGIS which one is the most accurate way to calculate distance between two points? 在PostgreSQL中的两个日期之间计算 - calculate between two dates in postgresql 如何获得两点之间的距离Postgres? - How to get distance between two points Postgres?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM