我有一个表(Table2),其中包含一些存储为地理数据类型的区域(多边形)。该表包含1529行。 在另一张表(表1)中,我有约。 22000行,每行有一个X / Y,我从中创建存储在Geography列中的Points。
我需要进行空间连接以找出每个点属于哪个区域。我在两个表上都创建了一个空间索引,但我觉得查询太慢了。现在,大约需要72秒来进行如下所示的连接:
SELECT ...
FROM [DatabaseA].dbo.Table1 t1
INNER JOIN [DatabaseB].dbo.Table2 t2 ON t1.Geo.STIntersects(t2.Geo) = 1
WHERE t2.ObjectTypeId = 1 AND t2.CompanyId = 3
请注意,这两个表位于不同的数据库中,但位于同一服务器上。
在创建空间索引之前,查询速度要慢得多,我可以看到正在使用索引。但是,在table2上创建索引不会影响性能,只有table1上的索引可以提供更好的性能。两个索引都有高级网格
当我查看执行计划时,我注意到一个过滤器部分占71%的时间:
CASE WHEN [Expr1015]>(2) THEN CASE WHEN [Expr1016]=[Expr1017] THEN (1) ELSE (0) END ELSE [DatabaseA].[dbo].[Table1].[Geo] as [t].[Geo].STIntersects([DatabaseB].[dbo].[Table2].[Geo] as [g].[Geo]) END=(1)
所以,我的问题是:
这个查询应该花这么长时间吗? 我应该使用其他网格尺寸吗? 这个过滤表达式意味着什么?
有没有人有优化这个的提示?
答案 0 :(得分:2)
我有类似的问题。我有2000点和85000多边形。我需要将点与匹配的多边形匹配。最初该查询需要8个小时。
SELECT Item.Name, Polygons.Name
FROM dbo.Geofence AS Polygons
JOIN dbo.ItemLocation AS Points
ON Polygons.GeoFence.STIntersects(Points.GeoLocation) = 1
问题是点表有一个非聚集索引。添加聚簇索引会将时间减少到12秒。
添加空间索引(下面的代码)会将时间减少到1秒。我还在积分表中添加了一个。
CREATE SPATIAL INDEX [SpatialIndex-Polygons] ON dbo.Polygons
(
[Geofence]
)USING GEOGRAPHY_GRID
WITH (GRIDS =(LEVEL_1 = MEDIUM,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = MEDIUM),
CELLS_PER_OBJECT = 16, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
答案 1 :(得分:1)
简而言之,您使用参数t2.Geo调用函数,该函数必须由函数计算t2中所有值的值,其中t2.ObjecttypeId = 1且t2.CompanyId = 3.在表上创建索引t2并没有真正帮助,因为它不能使用那些预先计算的索引值。相反,它必须首先对t2中的所有值运行函数t1.Geo.STIntersects(t2.Geo) - 它与预先计算的索引值几乎没有关系。
如果速度是您的目标并且您拥有存储空间,则可以创建第三个表,其中包含预先计算的t1.Geo.STIntersects(t2.Geo)的每个组合的结果。然后你可以将t1和t2连接到第三个表中的预先计算的值,它应该能够产生几乎即时的查询结果(对于包含1,529和22,000条记录的源表)。
如果t1和t2中的数据相对静态,您可以手动重新运行更新第三个表中数据的查询。如果它经常更改,它可以通过更新,插入和删除到t1和t2的触发器自动维护,或者您可以将更新,插入和删除包装到更新预计算表的存储过程中。