Sql server 为什么SQL Server中的空间搜索速度比PostGIS慢?
我正在努力将一些空间搜索功能从带有PostGIS的Postgres迁移到SQL Server,我看到一些非常糟糕的性能,甚至是索引 我的数据大约有一百万个点,我想找出这些点中哪些在给定的形状内,因此查询如下:Sql server 为什么SQL Server中的空间搜索速度比PostGIS慢?,sql-server,sql-server-2008,geospatial,spatial-index,Sql Server,Sql Server 2008,Geospatial,Spatial Index,我正在努力将一些空间搜索功能从带有PostGIS的Postgres迁移到SQL Server,我看到一些非常糟糕的性能,甚至是索引 我的数据大约有一百万个点,我想找出这些点中哪些在给定的形状内,因此查询如下: DECLARE @Shape GEOMETRY = ... SELECT * FROM PointsTable WHERE Point.STWithin(@Shape) = 1 如果我选择一个相当小的形状,我有时可以得到亚秒的时间,但如果我的形状相当大(有时是),我可以得到超过5分钟的时
DECLARE @Shape GEOMETRY = ...
SELECT * FROM PointsTable WHERE Point.STWithin(@Shape) = 1
如果我选择一个相当小的形状,我有时可以得到亚秒的时间,但如果我的形状相当大(有时是),我可以得到超过5分钟的时间。如果我在Postgres中运行相同的搜索,它们总是在一秒钟以下(事实上,几乎所有搜索都在200毫秒以下)
我在索引上尝试了几种不同的网格大小(全部高、全部中、全部低),每个对象有不同的单元格(16、64、256),无论我做什么,时间都保持相当恒定。我想尝试更多的组合,但我甚至不知道该往哪个方向走。每个对象有多个单元格?较少的一些奇怪的网格大小组合
我已经看过我的查询计划,他们总是使用索引,这根本没有帮助。我甚至在没有索引的情况下也尝试过,而且情况也不会更糟
在这方面有什么建议吗?我所能找到的一切都表明“我们不能给你任何关于索引的建议,只要尝试所有东西,也许一个就可以了”,但由于创建索引需要10分钟,盲目地这样做是一种巨大的时间浪费
编辑:
我也把这个贴在了。以下是他们要求提供的一些信息:
我能得到的最佳工作索引是:
CREATE SPATIAL INDEX MapTesting_Location_Medium_Medium_Medium_Medium_16_NDX
ON MapTesting (Location)
USING GEOMETRY_GRID
WITH (
BOUNDING_BOX = ( -- The extent of our data, data is clustered in cities, but this is about as small as the index can be without missing thousands of points
XMIN = -12135832,
YMIN = 4433884,
XMAX = -11296439,
YMAX = 5443645),
GRIDS = (
LEVEL_1 = MEDIUM,
LEVEL_2 = MEDIUM,
LEVEL_3 = MEDIUM,
LEVEL_4 = MEDIUM),
CELLS_PER_OBJECT = 256 -- This was set to 16 but it was much slower
)
我在使用索引时遇到了一些问题,但这是不同的
对于这些测试,我使用with(INDEX(…)子句为我的每个索引(测试网格大小和每个对象的单元格的各种设置)运行了一个测试搜索(在我的原始帖子中列出的一个),并且没有任何提示。我还使用每个索引和相同的搜索形状运行了sp_help_space_geometry_index。上面列出的索引运行最快,在sp_help_spatial_geometry_索引中也被列为效率最高的索引
运行搜索时,我会获得以下统计信息:
(1 row(s) affected)
Table 'MapTesting'. Scan count 0, logical reads 361142, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'extended_index_592590491_384009'. Scan count 1827, logical reads 8041, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
SQL Server Execution Times:
CPU time = 6735 ms, elapsed time = 13499 ms.
我还尝试使用随机点作为数据(因为我无法给出真实数据),但结果表明,使用随机数据进行搜索速度非常快。这让我们相信,我们的问题在于网格系统如何处理我们的数据
我们的数据是整个州的地址,因此有一些非常高密度的区域,但大部分是稀疏数据。我认为问题在于网格大小的设置对两者都不起作用。如果网格设置为高
,索引将在低密度区域返回太多的单元格,如果网格设置为低
,网格在高密度区域是无用的(在中等
,它没有那么差,但仍然不好)
我能够使用索引,但它没有帮助。每个测试都是在打开“show actual execution plan”(显示实际执行计划)的情况下运行的,它始终显示索引。以下是有关SQL Server空间扩展以及如何确保有效使用索引的一些说明:
exec sp_executesql
:
替换:
-- does not use the spatial index without a hint
declare @latlonPoint geometry = geometry::Parse('POINT (45.518066 -122.767464)')
select a.id, a.shape.STAsText()
from zipcodes a
where a.shape.STIntersects(@latlonPoint)=1
go
与:
我的直觉反应是“因为微软没有费心加快速度,因为它不是一个企业特性”。也许我是在玩世不恭
我也不知道为什么要从Postgres迁移。我不熟悉空间查询,但这可能是一个参数化查询问题 尝试使用固定值(使用参数化查询执行速度较慢的值)编写查询(不使用参数)并运行它。将时间与参数化版本进行比较。如果速度快得多,那么问题是参数化查询
如果上面的速度快得多,那么我将使用嵌入字符串中的参数值动态构建sql字符串,这样您就可以删除导致问题的参数。您是否正确设置了空间索引?您的边界框正确吗?所有的点都在里面吗?在您的情况下,网格的HHMM可能工作得最好(同样取决于布丁盒) 你能试着用sp\u help\u spatical\u geometry\u index看看有什么问题吗? 尝试使用过滤器操作,告诉我们您得到的性能值是多少?(它只执行主过滤器(使用索引),而不经过次过滤器(真正的空间操作))
您的设置有问题。空间确实是一个新特性,但也没那么糟糕 我相信STIntersects在使用索引时会更好地进行优化,它的性能会比Stin更好,尤其是对于较大的形状。您可以尝试将其分解为两个过程:
.Filter()
.STWithin()
选择*
)
这种微优化应该是没有必要的,但我以前看到过不错的性能改进。此外,你还可以通过(1)对(2)的比率来衡量指数的选择性。我刚刚花了一天时间研究了一个类似的问题。特别是,我们正在进行多边形中的点类型的查询,其中有一组相对较小的多边形,但每个多边形都很大且复杂 对于多边形表上的空间索引,解决方案如下:
-- this does use the spatial index without using a hint
declare @latlonPoint geometry = geometry::Parse('POINT (45.518066 -122.767464)')
exec sp_executesql
N'select a.id, a.shape.STAsText()
from zipcodes a
where a.shape.STIntersects(@latlonPoint)=1', N'@latlonPoint geometry', @latlonPoint
go
SELECT * INTO #this FROM PointsTable WHERE Point.Filter(@Shape) = 1
SELECT * FROM #this WHERE Point.STWithin(@Shape) = 1