2016-07-14 74 views
2

我有一个表点有一列的点类型GEOGRAPHY。我运行这段代码获得的最近点:选择最近的点sql server空间

DECLARE @Wgs84Longitude FLOAT; 
DECLARE @Wgs84Latitude FLOAT; 

DECLARE @Point GEOGRAPHY = Geography::STPointFromText(N'POINT(' 
              + CAST(@Wgs84Longitude AS NVARCHAR(MAX)) 
              + N' ' 
              + CAST(@Wgs84Latitude AS NVARCHAR(MAX)) 
              + N')', 4326); 

SELECT 
    TOP 1 
    * 
FROM Points 
ORDER BY @Point.STDistance(Point) ASC; 

积分表有这个索引:

CREATE SPATIAL INDEX SpatialIndex ON Points (Point); 

不幸的是,查询是相当缓慢。有什么我可以改进,使其更快(索引和/或查询明智)?

PS:

我也打了这方面的一些口味:

CREATE SPATIAL INDEX SpatialIndex ON [Core].[InternationalPostcodeList](Point) 
USING GEOGRAPHY_GRID 
WITH 
(
--BOUNDING_BOX =(-8.164229, 49.18581, 8.05384, 60.717093) 
     GRIDS=(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH) 
    , CELLS_PER_OBJECT = 64 
    , PAD_INDEX = OFF 
    , SORT_IN_TEMPDB = OFF 
    , DROP_EXISTING = OFF 
    , ALLOW_ROW_LOCKS = ON 
    , ALLOW_PAGE_LOCKS = ON 
) ON [PRIMARY]; 

的表现依然不能接受的。

回答

0

微软自己在MSDN上的文章提出了一些改进措施,可以确保“最近邻居”查询使用空间索引。主要的一点是我没有在WHERE子句中使用STDistance来限制距离(没有这个距离,它不能以任何方式过滤)。

尝试应用并查看是否可以提高性能。如果没有参考文章本身的进一步提示。

MSDN Nearest Neighbor

编辑

首先,你可以按如下简化查询创建点的过程:

DECLARE @Point GEOGRAPHY = GEOGRAPHY::Point(@latitude, @longitude, @srid); 

其次,它可能不会有所作为,但是你可以声明你的空间索引为HHHH,最多16个单元格(你可以选择一个)。在一天结束时,作为一个奇点,它只会在最低级别的索引中创建一条记录,但这取决于是否要在列中混合使用空间数据类型。

第三,我跑了几次测试,你应该很容易就能得到一秒钟的结果。我使用以下查询:

SELECT TOP 1 
* 
FROM 
Points P 
WHERE P.Point.STDistance(@Point) < (50 * 1609.344) -- 50 miles 
ORDER BY P.Point.STDistance(@Point) 

我的结果比1秒快很多。如果我省略WHERE子句,则时间大约减慢1500%(随着数据集大小而增加/减少)。但是这比你10-12秒的结果还要快。

您可以验证您的空间索引是否有效?如果没有,请尝试使用WITH(INDEX(SpatialIndex))提示。如果仍然不起作用,您可以上传您的查询执行计划吗?

+0

谢谢。当我按照文章中的建议介绍WHERE子句时,为了显然强制使用空间索引,查询执行速度更慢。 – cs0815

+0

@csetzkorn表格的大小(以行为单位)和你现在得到的次数是多少? –

+0

约250万行... – cs0815