Postgresql PgSql中查找大型数据集中最近邻的最佳查询是什么?

Postgresql PgSql中查找大型数据集中最近邻的最佳查询是什么?,postgresql,optimization,postgis,knn,nearest-neighbor,Postgresql,Optimization,Postgis,Knn,Nearest Neighbor,我有一个巨大的表,大约有4000万行,称为nearest_spot,以linestring格式表示行,它们最接近的点大约有1500个不同的点,存储在另一个表中。最近的_点表如下所示: data_id || spot_id || spot_name || link_geom 其中data_id是主键,spot_id是spot表主键的外键,spot_name是spot name我知道冗余不好,但我不允许修改数据库,link_geom是线坐标 数据库位于PostgreSQL 10.6、PostGIS

我有一个巨大的表,大约有4000万行,称为nearest_spot,以linestring格式表示行,它们最接近的点大约有1500个不同的点,存储在另一个表中。最近的_点表如下所示:

data_id || spot_id || spot_name || link_geom 其中data_id是主键,spot_id是spot表主键的外键,spot_name是spot name我知道冗余不好,但我不允许修改数据库,link_geom是线坐标

数据库位于PostgreSQL 10.6、PostGIS 2.5中,链接geom列有一个基本索引,最近的点表已经进行了真空分析

我的目标是尽可能快地找到该表中数据记录中某个点的最近邻

我已经知道如何找到最近的邻居,我的问题是找到它需要的时间。我对PostgreSQL和PostGIS非常陌生,我一直在阅读他们的文档,阅读了很多关于KNN优化的主题,我一直在寻找最有效的答案,但我无法在5分钟内得到结果,有时会达到30分钟,即使只搜索一行。我尝试过的不同查询如下:

SELECT *
FROM( SELECT A.position, B.spot_id
      FROM data A, nearest_spot B
      WHERE A.id = 1
      AND ST_DWithin(A.position,B.link_geom,20)
      ORDER BY A.position <-> B.link_geom
      LIMIT 10;)
ORDER BY ST_Distance(A.position,B.link_geom)
LIMIT 1;

SELECT *
FROM( SELECT A.position, B.spot_id
      FROM data A, nearest_spot B
      WHERE A.id = 1
      AND ST_Buffer(A.position,20) && B.link_geom
      ORDER BY A.position <-> B.link_geom
      LIMIT 10;)
ORDER BY ST_Distance(A.position,B.link_geom)
LIMIT 1;

SELECT *
FROM( SELECT A.position, B.spot_id
      FROM data A, nearest_spot B
      WHERE A.id = 1
      AND ST_Intersects(ST_Buffer(A.position,20), B.link_geom)
      ORDER BY A.position <-> B.link_geom
      LIMIT 10;)
ORDER BY ST_Distance(A.position,B.link_geom)
LIMIT 1;
我之所以先用ST_距离排序,然后用ST_距离排序,是因为根据PostGIS的结果,对于边界框来说,ST_距离更精确,但精度更低

我还将其用于空间索引,并将其用于操作符,两者都来自PostGIS


编辑:我意识到我所有的坐标都存储为几何体SRID4326,因此ST_DWithin调用虽然语法很好,但返回的所有行并非如预期的那样在20米以内,而是在地球20度以内的所有行,因此实际上我的ST_DWithin并没有使结果集变得更小,这可能是花费这么长时间的最大原因之一,圣尤缓冲区也是如此。在将坐标与米一起使用之前,我将尝试将所有坐标转换为geography with::geography,希望我能看到数据库需要做的改进?我认为最快的方法可能是加载 将1500个点放入空间索引中,例如KD树、四叉树或R树。然后在40M点上迭代,并在索引中搜索最近的邻居


不费吹灰之力,您应该能够每秒进行100000到500000次NN搜索,因此4000万次NN搜索应该需要大约2到5分钟。

似乎表格中有大量重复项,每行重复了大约1800次,给我的人根本不知道。删除重复项后,我的查询时间不再有问题了。

PostGIS提供了空间索引。@inc42是的,OP甚至写道他们使用了PostGIS空间索引,但显然速度太慢了。我不确定你的观点是什么?我不确定如果使用与PostGIS不同的空间索引和数据结构,你会想象到什么样的性能优势。为什么这比一个经过良好测试和验证的空间数据库要快?如果我错了,请纠正我,但PostGIS是一个插件/扩展/。。。对于PostgreSQL,它是一个关系数据库。这意味着它在管理ACID行为、查询处理、表到内存对象映射以及最有可能的磁盘I/O方面会带来大量开销。因此,我建议使用一些经过良好测试和验证的内存空间索引,而不是一个经过良好测试和验证的DBMS以及所有不必要的DBMS开销。为什么不快点呢?我想你会感到惊讶的。