【问题标题】:What is the fastest way to calculate and return the closest items in Table B from Table A within a set radius在设定的半径内,从表 A 计算和返回表 B 中最近的项目的最快方法是什么
【发布时间】:2019-02-13 14:46:38
【问题描述】:

我在表 1 和表 2 中有大量的纬度/经度坐标。例如,假设两个表中都有 100,000 个坐标。我需要从表 1 中返回表 2 中最接近的坐标对,只要它们在表 1 中的每个唯一项目(最多 100,000 个项目,但随后被剔除)的设定最小距离内(比如说,100 米)到 100 米是我的预期输出)。

我对 MSSQL 的几何和地理部分相当熟悉,并且通常会使用以下方法处理以下内容:

Select
Table1ID = T1.ID,
Table2ID = T2.ID,
Distance = T1.PointGeog.STDistance(T2.PointGeog),
Keep = 0
into #Distance 
From #Table1 T1
   cross join #Table2 T2
where T1.PointGeog.STDistance(T2.PointGeog) <= 100

这将返回 Table2 中距离 Table1 100 米范围内的所有项目

然后,为了仅限于最接近的项目,我可以:

Update #Distance
 set Keep = 1
from #Distance D 
   inner join 
   (select shortestDist = min(Distance), Table1ID from #Distance GROUP BY 
    Table1ID) A
    on A.ID = D.Table1ID and A.shortestDist = D.Distance

然后删除保留 1

的所有内容

这可行,但它绝对需要永远。交叉连接创建了 SQL 需要处理的大量计算,这导致在 MSSQL 2016 上大约需要 9 分钟的查询时间。我可以限制表 1 和表 2 与某些标准进行比较的部分的范围,但实际上不是很多。我只是真的不确定如何使这个过程更快。最终,我只需要:最近的项目,从 T2 到 T1 的距离。

我尝试了一些不同的解决方案,但我想看看 SO 社区是否有任何关于如何更好地优化此类问题的其他想法。

【问题讨论】:

    标签: sql tsql gis spatial


    【解决方案1】:

    尝试交叉应用:

    SELECT 
        T1.ID, TT2.ID, T1.PointGeog.STDistance(TT2.PointGeog)
    FROM #Table1 as T1
    CROSS APPLY (SELECT TOP 1 T2.ID, T2.PointGeog 
      FROM #Table2 as T2
      WHERE T1.PointGeog.STDistance(T2.PointGeog) <= 100
      ORDER BY T1.PointGeog.STDistance(T2.PointGeog) ASC) as TT2
    

    【讨论】:

      【解决方案2】:

      我尝试了一个新选项,我认为这是我计算出的最快的 - 大约 3 分钟。

      我将 Table1 更改为:

      select
      ID,
      PointGeog,
      Buffer = PointGeom.STBuffer(8.997741566866716e-4)
      into #Table1
      

      缓冲区为 100/111139(将度转换为米)

      然后

      if object_id('tempdb.dbo.#Distance') is not null
      drop table #Distance 
      Select 
      T1ID = T1.ID,
      T1Geog = T1.PointGeog,
      T2ID = T2.ID,
      T2Geog = T2.PointGeog,
      DistanceMeters = cast(null as float),
      DistanceMiles = cast(null as float),
      Keep = 0
      Into #Distance
      From #Table1 T1
          cross join #Table2 T2
      Where T1.Buffer.STIntersects(T2.PointGeom) = 1
      

      它不计算距离,但首先将数据集剔除到 100 米内的任何东西。然后我可以传递一个更新语句来计算一个更易于管理的数据集上的距离。

      【讨论】:

        【解决方案3】:

        在两个表的 geom 列上创建空间索引,性能应该不会太差。 比如:

        
        CREATE SPATIAL INDEX spat_t ON  [#Table1]
            (
                [PointGeog]
            )
        
        

        我在笔记本电脑上用 10 万个点进行了一些测试,“加入”花了 3 分钟

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-11-27
          • 1970-01-01
          • 1970-01-01
          • 2012-07-27
          • 1970-01-01
          • 2017-06-27
          相关资源
          最近更新 更多