【发布时间】:2008-12-22 15:12:17
【问题描述】:
我有一个存储经纬度坐标的表,我想进行查询,以获取某个点距离内的所有记录。
这个表有大约 1000 万条记录,并且在 Lat/Long 字段上有一个索引
这不需要很精确。除其他事项外,我正在考虑 1 度长 == 1 度纬度,我知道这不是真的,但我得到的椭圆足以达到此目的。
对于下面的示例,假设有问题的点是 [40, 140],而我的半径(以度为单位)是 2 度。
我试过这两种方法:
1) 我创建了一个 UDF 来计算 2 点之间距离的平方,并且我正在查询中运行该 UDF。
SELECT Lat, Long FROM Table
WHERE (Lat BETWEEN 38 AND 42)
AND (Long BETWEEN 138 AND 142)
AND dbo.SquareDistance(Lat, Long, 40, 140) < 4
我首先按正方形进行过滤,以加快查询速度并让 SQL 使用索引,然后对其进行细化以仅将落在圆圈内的记录与我的 UDF 匹配。
2) 运行查询以获取正方形(与之前相同,但没有最后一行),将所有这些记录提供给我的 ASP.Net 代码,并在 ASP.Net 端计算圆(同样的想法,计算保存 Sqrt 调用的距离的平方,并与我的半径的平方进行比较)。
令我惊讶的是,在 .Net 端计算圆的速度比使用 UDF 快大约 10 倍,这让我相信我在使用该 UDF 时做错了什么......
这是我正在使用的代码:
CREATE FUNCTION [dbo].[SquareDistance]
(@Lat1 float, @Long1 float, @Lat2 float, @Long2 float)
RETURNS float
AS
BEGIN
-- Declare the return variable here
DECLARE @Result float
DECLARE @LatDiff float, @LongDiff float
SELECT @LatDiff = @Lat1 - @Lat2
SELECT @LongDiff = @Long1 - @Long2
SELECT @Result = (@LatDiff * @LatDiff) + (@LongDiff * @LongDiff)
-- Return the result of the function
RETURN @Result
END
我在这里遗漏了什么吗?
在 SQL Server 中使用 UDF 不应该比提供给 .Net 所需的记录多 25% 的记录要快得多,还有 DataReader 的开销、进程之间的通信等等?
我在那个 UDF 中做错了什么导致它运行缓慢?
有什么办法可以改善吗?
非常感谢!
【问题讨论】:
标签: sql-server-2005 performance user-defined-functions