【问题标题】:Distance Calculation with huge SQL Server database使用庞大的 SQL Server 数据库进行距离计算
【发布时间】:2011-12-15 20:20:50
【问题描述】:

我有一个庞大的企业数据库(大约 500,000 个),其中包含邮政编码、地址等。我需要从 100 英里的用户邮政编码升序显示它们。我有一张带有相关纬度和经度的邮政编码表。什么是更快/更好的解决方案?

案例1:计算距离并按距离排序。我将在会话中为用户提供当前的邮政编码、纬度和经度。我将使用 SQL Server 函数计算距离。

案例 2:获取 50 英里区域内的所有邮政编码,并获得所有这些邮政编码的企业。在这里,我将不得不在查找业务时在嵌套查询中编写一个选择。

我认为案例 1 将计算数据库中所有企业的距离。而第二种情况只会获取邮政编码,最终只会获取所需的业务。因此案例2应该更好?如有任何建议,我将不胜感激。

这是我对案例 1 的 LINQ 查询。

var businessListQuery = (from b in _DB.Businesses
                         let distance = _DB.CalculateDistance(b.Zipcode,userLattitude,userLogntitude)
                         where b.BusinessCategories.Any(bc => bc.SubCategoryId == subCategoryId)
                                         && distance < 100
                         orderby distance
                         select new BusinessDetails(b, distance.ToString()));

int totalRecords = businessListQuery.Count();
var ret = businessListQuery.ToList().Skip(startRow).Take(pageSize).ToList();

顺便说一句,应用程序是用 C# 编写的。

谢谢

【问题讨论】:

  • 编写 sql 并运行执行计划和统计信息,看看哪个更快。如果性能是一个问题,请编写一个存储过程并在数据库中执行此操作并进行比较。
  • 创建索引视图并在您的索引中使用邮政编码,然后它会给您更快的结果尝试这种方式,或者可能会根据您的搜索和顺序更改您的索引。
  • @f00 但在这种情况下,如果我必须更改距离,则必须重新填充表。

标签: sql-server performance linq sql-server-2008


【解决方案1】:

您可能比查看GEOGRAPHY 数据类型更糟糕,例如:

CREATE TABLE Places
(
    SeqID       INT IDENTITY(1,1),
    Place       NVARCHAR(20),
    Location    GEOGRAPHY
)
GO
INSERT INTO Places (Place, Location) VALUES ('Coventry', geography::Point(52.4167, -1.55, 4326))
INSERT INTO Places (Place, Location) VALUES ('Sheffield', geography::Point(53.3667, -1.5, 4326))
INSERT INTO Places (Place, Location) VALUES ('Penzance', geography::Point(50.1214, -5.5347, 4326))
INSERT INTO Places (Place, Location) VALUES ('Brentwood', geography::Point(52.6208, 0.3033, 4326))
INSERT INTO Places (Place, Location) VALUES ('Inverness', geography::Point(57.4760, -4.2254, 4326))
GO
SELECT p1.Place, p2.place, p1.location.STDistance(p2.location) / 1000 AS DistanceInKilometres
    FROM Places p1
    CROSS JOIN Places p2
GO  
SELECT p1.Place, p2.place, p1.location.STDistance(p2.location) / 1000 AS DistanceInKilometres
    FROM Places p1
        INNER JOIN Places p2 ON p1.SeqID > p2.SeqID
GO  

geography::Point 接受纬度和经度以及 SRID(特殊参考 ID 号)。在这种情况下,SRID 为 4326,即标准纬度和经度。由于您已经有了纬度和经度,您只需 ALTER TABLE 添加地理列,然后 UPDATE 填充它。

我已经展示了两种从表中获取数据的方法,但是您不能使用此方法创建索引视图(索引视图不能具有自联接)。您可以创建一个实际上是缓存的辅助表,该表是根据上述内容填充的。然后你只需要担心维护它(可以通过触发器或其他一些过程来完成)。

请注意,交叉连接将为您提供 250,000,000,000 行,但搜索很简单,因为您只需查看其中一个位置列(即SELECT * FROM table WHERE Place1 = 'Sheffield' AND distance &lt; 100,第二个将为您提供更少的行,但查询需要考虑 Place1 和 Place2 列)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-14
    • 2020-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    相关资源
    最近更新 更多