T-SQL Fastforward Cursor vs. foreach

时间:2011-01-27 14:13:05

标签: c# sql-server tsql

我希望计算gps-point之间的距离,以获得第一个和最后一个点之间的完整距离。

我的问题是:什么更快?

  • 将所有行加载到DataTable中 通过foreach在c#.net中计算它 或
  • 使用a在Sql-Server上对其进行计算 带有FastForward的StoredProcedure 光标。

我谈到大约有400,000行。

4 个答案:

答案 0 :(得分:4)

我肯定会尝试在服务器上执行此操作 - 尽量避免拖动400'000行来计算单个数字(最后)。

另外:如果可能的话,我会尝试没有光标。游标是SQL Server的噩梦 - 应该不惜一切代价避免它们。

在你的情况下 - 不知道你的详细表结构 - 你绝对可以做到,例如一个递归的CTE(公用表表达式),以第一个元素开始,总距离为0.0,然后递归地求和所有其他路径点,计算点(x + 1)和点x之间的距离,并求和以前的总数。

最后,你应该有一个CTE,显示所有航路点,任何两个航点之间的所有距离,以及整个旅程的总距离。

CTE会是这样的:

;WITH Waypoints AS
(
    -- anchor your query
    SELECT
       WaypointID, PrevWaypointID, Long, Lat, 0.0 as Distance, 0.0 as SumOfDistance
    FROM
       dbo.Waypoint
    WHERE
       PrevWaypointID IS NULL  --  or some other condition

    UNION  -- recurse

    SELECT
       WaypointID, Long, Lat, 
       dbo.GetDistanceBetween(wp.WaypointID, pts.WaypointID),   -- distance
       pts.SumOfDistance + dbo.GetDistanceBetween(wp.WaypointID, pts.WaypointID)  -- sum
    FROM
       dbo.Waypoint wp
    INNER JOIN
       Waypoints pts ON wp.PrevWaypointID = pts.WaypointID          
    WHERE
       (some condition; ID = 1 or PreviousWaypointID IS NULL or something)
)
SELECT * FROM Waypoints

答案 1 :(得分:3)

如果您使用的是SQL Server 2008,我建议您尝试将它们存储为geography类型,然后

declare @point1 geography = 'POINT (-42 84)';
declare @point2 geography = 'POINT (-3 10)';
select @point1.STDistance (@point2)

但要真正了解什么是最快的,你必须尝试两者。

答案 2 :(得分:2)

我的理解是,即使在SQL中使用Cursor,它仍然比在前端代码中迭代快几个数量级。当时,ADO和DAO都是有问题的技术,因此随着ADO.NET和DataSet的出现,情况可能会有所改变。

但是,我认为专门为这类事物设计的T-SQL仍然更有效率。

如果你需要在迭代期间应用特殊逻辑,可能会出现异常,但我认为正确设置SQL Cursor,在背面执行计算,将胜过数据集。

如果你能做的话,最好的办法是在SQL中没有光标的情况下这样做。 。

答案 3 :(得分:2)

如果您正在使用Sql Server 2008(或更新版本),那么您可以使用地理类型在服务器上执行所有操作。以下是计算两点之间距离的示例:

SELECT geography::Point(lat1, lon1, 4326).STDistance(geography::Point(lat2, lon2, 4326))

我不确定这是否可以在没有光标的情况下使用,但也许。

如果您使用的是旧版本的SQL Server,那么您仍然可以将距离公式自己编写为存储过程,并在服务器端执行所有操作。

将整个集合下载到客户端并进行客户端的所有计算几乎肯定会花费更长的时间,因为下载时间将远远大于计算时间。