【发布时间】:2015-11-16 09:54:28
【问题描述】:
在this recommendation 进行优化的最近邻更新之后,我正在使用下面的 tsql 更新一个包含 11,000 个点的 GPS 表,其中每个点最近的兴趣点。
WHILE (2 > 1)
BEGIN
BEGIN TRANSACTION
UPDATE TOP ( 100 ) s
set
[NEAR_SHELTER]= fname,
[DIST_SHELTER] = Shape.STDistance(fshape)
from(
Select
[dbo].[GRSM_GPS_COLLAR].*,
fnc.NAME as fname,
fnc.Shape as fShape
from
[dbo].[GRSM_GPS_COLLAR]
CROSS APPLY (SELECT TOP 1 NAME, shape
FROM [dbo].[BACK_COUNTRY_SHELTERS] WITH(index ([S50_idx]))
WHERE [BACK_COUNTRY_SHELTERS].Shape.STDistance([dbo].[GRSM_GPS_COLLAR].Shape) IS NOT NULL
ORDER BY BACK_COUNTRY_SHELTERS.Shape.STDistance([dbo].[GRSM_GPS_COLLAR].Shape) ASC) fnc)s;
IF @@ROWCOUNT = 0
BEGIN
COMMIT TRANSACTION
BREAK
END
COMMIT TRANSACTION
-- 1 second delay
WAITFOR DELAY '00:00:01'
END -- WHILE
GO
请注意,我以 100 个为一组来避免锁定,如果我不将其分块,我会得到它,并且它会运行几个小时,然后我必须杀死它。显而易见的答案是“您是否优化了空间索引”,答案是肯定的,两个表都有一个空间索引(SQL 2012),Geography Autogrid,每个对象 4092 个单元格,经过多天的研究,发现这是最有效的索引测试索引参数的所有可能排列。我已经尝试过使用和不使用空间索引提示......使用多个空间索引。
在上面,请注意空间索引查找成本和关于无列统计信息的警告,据我所知,空间索引就是这种情况。在每种情况下,我最终都必须终止 tsql。它只是永远运行(在一种情况下是一夜之间,更新了 2300 行)。
我已经尝试过Isaac's numbers table join solution,但该示例似乎不适合循环 n 距离搜索,只是一个用户提供的位置 (@x)。
更新
@ Brad D 根据您的回答,我尝试了这个,但有一些我无法弄清楚的语法错误......我不确定我是否正确地将您的示例转换为我的示例。任何想法我做错了什么?谢谢!
;WITH Points as(
SELECT TOP 100 [NAME], [Shape] as GeoPoint
FROM [BACK_COUNTRY_SHELTERS]
WHERE 1=1
SELECT P1.*, CP.[GPS_POS_NUMBER] as DestinationName, CP.Dist
INTO #tmp_Distance
FROM [GRSM_GPS_COLLAR] P1
CROSS APPLY (SELECT [NAME] , Shape.STDistance(P1.GeoPoint)/1609.344 as Dist
FROM [BACK_COUNTRY_SHELTERS] as P2
WHERE 1=1
AND P1.[NAME] <> P2.[NAME] --Don't compare it to itself
) as CP
CREATE CLUSTERED INDEX tmpIX ON #tmp_Distance (name, Dist)
SELECT * FROM
(SELECT *, ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Dist ASC) as Rnk FROM #tmp_Distance) as tbl1
WHERE rnk = 1
DROP TABLE #tmp_Distance
【问题讨论】:
-
您还应该发布查询
explain。您为单个点查找邻居的查询时间是多少?我使用类似于 Isaac 样本的东西。我创建了一个函数,然后使用该函数进行更新。 -
tsql 查询从 op 中的第 3 行开始。单点搜索...小于 0.01 秒。当它搜索 n 行中的每一行的最近邻居时,它就会锁定。
-
那么搜索邻居不是问题。创建您的
function(gps_id) return id。只需执行update set neighbordid = function(gps_id)。我希望我能提供更多帮助,但我更多的是 postgresql postgis 类型。 -
将一个行 ID 和你最近的邻居写入另一个表是一个想法吗?这里几点了?你可以把这个写回去……在一个同时大量更新的表中进行繁重的计算总是很困难的……
标签: sql sql-server tsql nearest-neighbor spatial-index