如何有效地确定圆内的n个位置?

时间:2012-04-18 14:29:56

标签: c# sql-server performance google-maps geolocation

鉴于此情况:

  1. 我们在全球范围内拥有1,000,000点的订单,由经度和纬度指定;
  2. 我们有一个基于点pc的圆圈c(由经度和纬度指定)和半径rc
  3. 我们希望有效地确定圈子中的哪个点
  4. 我正在使用C#和SQL Server 2008中存储的位置进行开发。

    所以我看到它有这3个选项:

    1. 将位置存储为经度纬度浮点数并在C#中执行计算。

    2. 将位置存储为地理数据类型,并在SQL Server 2008中执行计算,如下所示:

      CREATE TABLE UserLocations
      [UserId] [bigint] NOT NULL,
      [CurrentLocation] [geography] NOT NULL
      
      ALTER PROCEDURE sp_GetCurrentUsersInRange
      @userPoint geography, 
      @RangeInMeters int
      AS
      BEGIN
      
      select  UserId from UserLocations
      where @userPoint.STDistance(CurrentLocation) <= @RangeInMeters
      and UserId <> @userId
      
      END
      

      缺点:使用LinqToSQL和LinqToEntities的地理数据时出现问题。

      优点:对大数据使用dbms处理能力,并使用SQL Server空间索引。

    3. 3.使用谷歌的地理位置和计算服务等网络服务。 到目前为止,我没有找到这样的网络服务。

      您认为哪种效率最高?请证明您的答案合理。

      谢谢

2 个答案:

答案 0 :(得分:1)

我天真的方法是在点pc周围定义一个纬度/长度边界框,并在这些框坐标上使用BETWEEN从数据库中进行选择。统计上,通过该测试的点数中约有79%将在圈内。对代码进行简单检查就可以清除圈外的内容。

我说天真,因为我不熟悉SQL Server的几何功能。

答案 1 :(得分:0)

使用几何圆的替代方法,您可以从圆的中心选择一定距离内的所有记录(使用STDistance)。但我不知道它是否比你列出的交叉解决方案更快或更慢。

如果100,000点是静态的,你可以在C#中编写代码,将列表加载到内存中并使用边界框来最小化距离计算的使用(即,Haversine)。它可能会更快,因为你最小化I / O.

但是,如果这些点不是静态的(或者它们存储在SQL Server中),我会选择使用SQL Server,这样会容易得多。你肯定想要创建适当的空间索引。 SQL Server的空间索引非常好,您可能会发现它甚至可以超出我上面列出的内存解决方案。

我没有使用LINQ进行此类工作,我通常使用SqlConnection和Reader进行老式学习。我已经读过LINQ与Spatials混合是一个问题。

我不知道谷歌,他们有这样的网络服务吗?