【发布时间】:2019-04-30 13:10:11
【问题描述】:
更新:写这篇文章后,我们决定将我们的地理空间数据迁移到 ElasticSearch 数据库,这样会产生更好的结果。
我是 SQL 新手,我需要帮助来优化空间查询,使其在 2 秒内运行。我们已经尝试了在各种网站上找到的一些建议(更多内容见下文)。
背景
我们有一个表 [Id, Geometry],其中包含大约 300,000 个不同大小和复杂性的几何形状,存储为几何数据类型。我们使用下面的代码 sn-p 为 Geometry 创建了空间索引。
CREATE SPATIAL INDEX [IX_Geometry_Spatial]
ON [dbo].[Geometries] ([Geometry]) USING GEOMETRY_AUTO_GRID
WITH (
BOUNDING_BOX = (XMAX = 24.43359375, XMIN = 10.810546875, YMAX = 69.2249968541159, YMIN = 55.2791152920156)
);
我们想要的是找到与输入几何形状相交的所有几何形状。这是通过使用以下查询完成的。
DECLARE @g geometry;
SET @g = geometry::STGeomFromText('POLYGON ((x0 y0, ...))', 4326); -- A Worst Case Polygon containing 1442 data points
SELECT Count(Id)
FROM Geometries
WHERE Geometries.Geometry.Filter(@g.Reduce(.25)) = 1
对于一些最坏的输入几何形状(大的复杂多边形),此执行大约需要 7-10 秒。
我们可以看到我们命中了空间索引,但最昂贵的操作是clustered index seek (Clustered)
聚集索引查找详细信息:
空间索引查找详细信息:
问题
不应该由空间索引而不是聚集索引来完成繁重的工作吗?
可以通过更改空间索引的设置来改进查询吗?我们应该使用哪些设置(对于 GRIDS、CELLS_PER_OBJECT 等)?
如何才能整体缩短执行时间,或者这种查询的预期时间是 7-10 秒?
我们尝试过的,有帮助的
每个都节省了大约几秒钟。
- 检查索引碎片,并重建索引。
- 从
STIntersect()切换到Filter()的交集方法 - 使用
Reduce(.25)减少了输入几何。这将几何图形从 1442 个数据点减少到 7 个。(如果我们决定使用它,它必须是动态的以适应不同的输入,但这是另一个问题。) - 引入了一个新的表格列
SimpleGeometry,其中包含来自Geometry列的所有几何对象的边界框。创建了一个新的SimpleGeometry空间索引并使用SimpleGeometry代替Geometry进行查找。 (在查询示例中未使用。)
【问题讨论】:
-
我建议做更多的预处理。你从边界框开始没问题。我会通过制作一个 3d 网格来改进这一点,每个网格立方体都会保存一个干扰它的对象列表。目标应该是尽快改善最近物体的位置,然后用尽可能少的物体进行详细计算。
-
我认为最大的问题可能是表值函数。那些事情就像倒着骑乌龟一样慢。
-
我有一个类似的查询,其中空间索引未用于搜索。尝试使用 WITH (INDEX([Index_Name])) 强制 SQLServer 使用索引。
SELECT TOP (1) * FROM myTable ga WITH(INDEX([SpatialIndex_sptGeoPolygonBounds])) WHERE ga.sptGeoPolygonBounds.STIntersects(@point) = 1
标签: sql sql-server elasticsearch spatial-query spatial-index