与庞大的SQL Server数据库进行距离计算

时间:2011-12-15 20:20:51

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

我有一个庞大的商业数据库(约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#。

由于

1 个答案:

答案 0 :(得分:4)

您可能会比查看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 < 100,第二个将显着减少行数,但查询然后需要考虑Place1和Place2列。)