从地理信息列中搜索附近的点

3

我在我的表中有一个带有空间索引的地理类型列。如何使用索引提高性能,选择距离给定的纬度/经度X米以内的前N行?

1个回答

7
当你说“利用索引”的时候,你是什么意思?
我刚刚开始(今天)尝试使用SQL 2012及其Geography数据类型,但也许下面的内容有用-我知道你使用的是2008-R2 创建一些数据:
CREATE TABLE SpatialTable 
    ( id int IDENTITY (1,1) PRIMARY KEY,
    GeogCol1 geography, 
    GeogCol2 AS GeogCol1.STAsText() );
GO

INSERT INTO SpatialTable (GeogCol1)
VALUES 
(geography::STGeomFromText('POINT(-122.360 47.656)',4326)),
(geography::STGeomFromText('POINT(-122.343 47.656)',4326)),
(geography::STGeomFromText('POINT(-122.358 47.660)',4326)),
(geography::STGeomFromText('POINT(-122.348 47.649)',4326)),
(geography::STGeomFromText('POINT(-122.348 47.658)',4326)),
(geography::STGeomFromText('POINT(-122.358 47.653)',4326))

创建索引:

CREATE SPATIAL INDEX Spatialindex ON SpatialTable ( GeogCol1 ) USING GEOGRAPHY_GRID 
WITH (
    GRIDS =(LEVEL_1 = MEDIUM,LEVEL_2 = MEDIUM,LEVEL_3 = MEDIUM,LEVEL_4 = MEDIUM),
    CELLS_PER_OBJECT = 16, PAD_INDEX  = OFF, SORT_IN_TEMPDB = OFF,
    DROP_EXISTING = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON
)

定义兴趣点:

DECLARE @g geography;
SET @g = geography::STGeomFromText('POINT(-122.34900 47.65100)', 4326);

找出距离点750米以内最近的2个对象。

SELECT TOP 2
        @g.STDistance(st.GeogCol1) AS [DistanceFromPoint (in meters)] 
    ,   st.GeogCol2
    ,   st.id
FROM    SpatialTable st WITH(INDEX(SpatialIndex))
WHERE   @g.STDistance(st.GeogCol1) <= 750
ORDER BY @g.STDistance(st.GeogCol1) ASC

提供:

DistanceFromPoint (in meters) GeogCol2                 id
----------------------------- ------------------------ -----------
234.715604015178              POINT (-122.348 47.649)  4
711.760044795868              POINT (-122.358 47.653)  6
SQL执行计划显示索引被使用了,而该网站显示返回的距离是正确的。
如果这不是您需要的,请让我知道。我也在学习这个领域,所以任何修改都是有益的!
***编辑**** 我已经添加了一个索引表提示,强制查询使用该索引(根据此MSDN文章)。该链接解释了最初可能没有使用该索引,因为SQL确定不使用该索引会更快。上面的例子中,执行计划显示97%/ 3%的使用/未使用索引,因此在这种情况下,SQL优化器的想法是正确的。
为什么在使用索引时查询会变慢似乎是众多博客文章和SO上的问题的主题。

看起来这就是需要的。我会检查一下是否使用了我添加的空间索引。 - Bahamut
执行计划没有显示它正在使用空间索引。 - Bahamut
@Bahamut 根据(http://blogs.msdn.com/b/isaac/archive/2008/08/29/is-my-spatial-index-being-used.aspx),我已经添加了一个索引提示,它有效了。 - Morphed
嘿,谢谢Paddy,这个有效,我用谷歌地图上实际的纬度和经度进行了验证。我唯一的问题是,这返回给我两点之间的实际距离,据我理解,这是空中距离...对吗? - Sandesh Daddi
STDistance() 返回两个地理类型之间的最短 LineString。这是大圆距离的近似值。在常见的地球模型上,STDistance() 的偏差与精确的大圆距离之间的差异不超过0.25%。这避免了在大圆类型中长度和距离之间微妙差异的混淆。 - Morphed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接