我有不规则形状的地理区域。地理字段可以从定义该形状的数百到数千个纬度/长点变化。在尺寸方面,它可能来自几个美国。邮政编码达到整个美国的大小。为了提高性能,我在该字段上构建了Spacial索引。我经常需要找到基于特定区域内的纬度/长点的车辆。
我最初的做法就是这个。
WITH LastP
AS ( SELECT vlp.ID
,GEOGRAPHY::STPointFromText('POINT(' + CAST(vlp.Long AS VARCHAR(20)) + ' '
+ CAST(vlp.Lat AS VARCHAR(20)) + ')', 4326) AS LastKnownPoint
FROM LastPosition AS vlp )
SELECT lp.ID
,zn.ZONE
FROM dbo.GeogZone AS zn WITH ( NOLOCK )
JOIN @zones AS z
ON zn.Zone = z.Zone
JOIN LastP AS lp
ON lp.LastKnownPoint.STWithin(zn.ZoneGeog) = 1
我从表格LastPosition
获取所有记录,而不是使用Geography
函数将Lat / Long转换为JOIN
点,然后转换为STWithin
。这个过程很有效但速度很慢。我试图调整Spacial索引,但它没有发生重大变化。
为了提高性能,我想介绍以下过程。
从地理位置类型我将提取NorthLat, SouthLat, EastLong, WestLong
现在我可以在以下事项进行比较之前限制结果数量。
WITH LastP
AS ( SELECT vlp.ID
,GEOGRAPHY::STPointFromText('POINT(' + CAST(vlp.Long AS VARCHAR(20)) + ' '
+ CAST(vlp.Lat AS VARCHAR(20)) + ')', 4326) AS LastKnownPoint
FROM LastPosition AS vlp
WHERE (vlp.Long BETWEEN @WestLong and @EastLong) AND (vlp.Lat BETWEEN @SouthLat AND @NorthLat))
SELECT lp.ID
,zn.ZONE
FROM dbo.GeogZone AS zn
JOIN @zones AS z
ON zn.Zone = z.Zone
JOIN LastP AS lp
ON lp.LastKnownPoint.STWithin(zn.ZoneGeog) = 1
以下是构建框的代码。
DECLARE @geomenvelope GEOMETRY;
DECLARE @BoundingBox AS TABLE
(
SouthLat DECIMAL(10, 8)
,NorthLat DECIMAL(10, 8)
,EastLong DECIMAL(10, 8)
,WestLong DECIMAL(10, 8)
);
SELECT @geomenvelope = GEOMETRY::STGeomFromWKB(zn.ZoneGeog.STAsBinary(), zn.ZoneGeog.STSrid).STEnvelope()
FROM dbo.GeogZone AS zn
WHERE zn.Zone = 'CA-1'
INSERT INTO @BoundingBox (SouthLat,NorthLat,EastLong,WestLong)
SELECT @geomenvelope.STPointN(1).STY
,@geomenvelope.STPointN(3).STY
,@geomenvelope.STPointN(1).STX
,@geomenvelope.STPointN(3).STX
SELECT *
FROM @BoundingBox
我的问题:是否有另一种(更简单的)方法可以从我的地理领域获得东,西,北,南点?
答案 0 :(得分:0)
很抱歉迟到的回复,但希望我能加点。
首先,转换为LastKnownPoint,您应该可以按如下方式声明:
GEOGRAPHY::Point(vlp.Lat, vlp.Long, 4326) AS LastKnownPoint
它的工作原理相同,但必须更容易阅读,不需要演员表。
为了获得更好的性能,如果您可以将Lat / Long存储为Geography列本身,则不必进行转换,如果您经常搜索会产生大量开销。这样做也可以让你直接使用Zone作为过滤器并使用空间索引,我不能高度推荐它。更不用说不再需要创建边界框了。
如果你不能做到这一切,至少减少CAST'ing和连接应该会在这里和那里获得相当长的几毫秒。