got*_*tqn 7 sql-server sql-server-2012 spatial
我在存储过程执行期间使用以下结构创建临时表:
[ID] BIGINT
[Point] GEOGRAPHY
Run Code Online (Sandbox Code Playgroud)
该ID
不是唯一的-大约有200
每个记录ID
。
我需要找到一个不同的列表,IDs
其中至少有一个Point
比Point
常量值(例如200
米)大的距离。
所以,我正在使用这样的东西:
SELECT DISTINCT DS1.[ID]
FROM DataSource DS1
INNER JOIN DataSource DS2
ON DS1.[ID] = DS2.[ID]
WHERE DS1.Point.STDistance(DS2.Point) > 200
Run Code Online (Sandbox Code Playgroud)
对于 23 000 个点,查询执行4-5
几秒钟。因为我期待有更多的价值,所以我需要找到更好的解决方案。
我想如果有更快的方法,我总是可以创建一个物化表并实现额外的逻辑来计算它ID
。
我创建了一个空间索引,但查询优化器没有使用它。如果我使用hint
这样的WITH (INDEX(SPATIAL_idx_test))
我会收到以下错误:
消息 8635,级别 16,状态 4,第 78 行
查询处理器无法为带有空间索引提示的查询生成查询计划。原因:空间索引不支持谓词中提供的比较器。尝试删除索引提示或删除SET FORCEPLAN
. `
无论您进行任何其他改进,请务必测试启用跟踪标志 6532、6533 和 6534(仅限启动)对空间执行时间的影响。这些打开本机代码空间实现。需要 SQL Server 2012 Service Pack 3 或 SQL Server 2014 Service Pack 2(Microsoft 支持文章)。默认情况下,本机编译从 SQL Server 2016 开始。
对于STDistance
重要的跟踪标志是6533。在一个简单的测试中,这将执行时间从 2100 毫秒提高到 150 毫秒而无需在我笔记本电脑的 SQL Server 2012 实例上使用空间索引。
改编自SQL 2016 的示例——它运行得更快: Bob Ward 的原生空间实现):
CREATE TABLE dbo.SpatialTest
(
ID integer NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED,
Points geography NOT NULL
);
GO
-- Insert random sample points
SET NOCOUNT ON;
GO
DECLARE @Point float = 1.1;
INSERT dbo.SpatialTest (Points)
VALUES ('POINT(' + CAST(@Point AS varchar(20)) + ' ' + CAST(@Point AS varchar(20)) + ')' );
WHILE(SCOPE_IDENTITY() < 100000)
BEGIN
SET @Point = @Point + RAND(SCOPE_IDENTITY());
IF (@Point > 90.0)
BEGIN
SET @Point = -89.0 + RAND(SCOPE_IDENTITY());
END;
INSERT dbo.SpatialTest (Points)
VALUES ( 'POINT(' + CAST(@Point AS varchar(20)) + ' ' + CAST(@Point AS varchar(20)) + ')' );
END;
Run Code Online (Sandbox Code Playgroud)
DBCC TRACEON (6533);
DBCC TRACESTATUS;
GO
DECLARE
@s datetime2 = SYSUTCDATETIME(),
@g geography = 'POINT(1.0 80.5)';
SELECT [Matches] = COUNT_BIG(*)
FROM dbo.SpatialTest AS ST
WHERE ST.Points.STDistance(@g) > 10000000.5
OPTION (MAXDOP 1, RECOMPILE);
SELECT [Elapsed STDistance Query (ms)] = DATEDIFF(MILLISECOND, @s, SYSUTCDATETIME());
Run Code Online (Sandbox Code Playgroud)
平均执行时间:2100ms(trace flag off);150ms(跟踪标志打开)。