我的查询花费的时间太长而且经常超时。它是基于邻近度的邮政编码搜索表值函数。无论如何都要根据查询进行索引,所以它不必每次重新计算所有这些值吗?邮政编码和邮政编码列表合计超过一百万行。
这是表函数。
Create FUNCTION [dbo].[ZipsInRadius] (@zipCode varchar(15),
@radius int, @unit char(1))
RETURNS @areaResults TABLE(
Zip varchar (30),
City varchar (255),
St varchar (20),
Lat decimal (16,12),
Long decimal (16,12))
BEGIN
DECLARE @iStartLat decimal(16, 12)
DECLARE @iStartLong decimal(16, 12)
SELECT
@iStartLat = CAST(Latitude AS decimal(16, 12)),
@iStartLong = CAST(Longitude AS decimal(16, 12))
FROM zip
WHERE zipcode LIKE @zipCode + '%'
SELECT
@iStartLat = CAST(Latitude AS decimal(16, 12)),
@iStartLong = CAST(Longitude AS decimal(16, 12))
FROM postalcode
WHERE postalcode LIKE @zipCode + '%'
DECLARE @latRange decimal(16, 12)
DECLARE @longRange decimal(16, 12)
IF (@unit = 'K') --Get distance in kilometers
BEGIN
SELECT @LatRange =
(CAST(@radius / ((6076.0 / 5280.0) * 60.0)
AS decimal(16, 12))) * 0.621371
SELECT @LongRange =
(@radius / (((cos(@iStartLat * pi() / 180.0) * 6076.0)
/ 5280.0) * 60)) * 0.621371
END
ELSE --Get distance in miles (the default)
BEGIN
SELECT @LatRange = CAST(@radius / ((6076.0 / 5280.0) * 60.0)
AS decimal(16, 12))
SELECT @LongRange =
@radius / (((cos(@iStartLat * pi() / 180.0) * 6076.0)
/ 5280.0) * 60)
END
DECLARE @lowLatitude decimal(16, 12)
DECLARE @highLatitude decimal(16, 12)
DECLARE @lowLongitude decimal (16, 12)
DECLARE @highLongitude decimal (16, 12)
SELECT @lowLatitude = @iStartLat - @latRange
SELECT @highLatitude = @iStartLat + @latRange
SELECT @lowLongitude = @iStartLong - @longRange
SELECT @highLongitude = @iStartLong + @longRange
INSERT INTO @areaResults (zip, city, st, lat, long)
SELECT ZIPcode, CITY, STate, LATitude, LONGitude
FROM Zip Z
WHERE Z.Latitude <= @highLatitude
AND Z.Latitude >= @lowLatitude
AND Z.Longitude >= @lowLongitude
AND Z.Longitude <= @highLongitude
INSERT INTO @areaResults (zip, city, st, lat, long)
SELECT postalcode, CITY, province, LATitude, LONGitude
FROM postalcode z
WHERE Z.Latitude <= @highLatitude
AND Z.Latitude >= @lowLatitude
AND Z.Longitude >= @lowLongitude
AND Z.Longitude <= @highLongitude
RETURN
END
答案 0 :(得分:3)
这需要我几毫秒,也许你的方法是错误的看看这里:SQL Server Zipcode Latitude/Longitude proximity distance search 2000/2005版本
或在2008版本中使用地理数据类型:SQL Server 2008 Proximity Search With The Geography Data Type
答案 1 :(得分:2)
我建议在经度和纬度上使用多列索引。
使用边界框很好,这通常可以加快查询速度。根据我提到的索引,您应该看到巨大的改进。
在旁注中,您的纬度/经度存储在十进制(16,12)中。 12位数的精度可能超过您的需要。第五位(以纬度/长度为单位)表示大约3英尺。所以......第12位可能实际上代表纳米(或更小)。通过使用较小的数据类型,您的表(和索引)将更有效。对于邮政编码搜索尤其如此,因为您拥有的纬度/长度是一个代表邮政编码中心的点,位置不是很精确。对于经度,我通常使用十进制(8,5)。由于纬度通常在-90到90的范围内,因此您可以使用十进制(7,5)来获得纬度。
答案 2 :(得分:1)
您可以尝试在索引上强制INDEX JOIN
,看看它是否有帮助:
CREATE INDEX ix_zip_lat ON zip(lat)
CREATE INDEX ix_zip_long ON zip(long)
SELECT * FROM zip
WITH (INDEX(ix_zip_lat), INDEX (ix_zip_long))
WHERE lat BETWEEN @lowlat and @hilat
AND long BETWEEN @lowlong and @hilong