4

我有一个表(Table2),其中包含一些存储为地理数据类型的区域(多边形)。该表包含 1529 行。在另一个表(表 1)中,我有大约。22000 行,每行都有一个 X/Y,我从中创建存储在 Geography 列中的点。

我需要进行空间连接以找出每个点属于哪个区域。我在两个表上都创建了空间索引,但我认为查询太慢了。现在,连接大约需要 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)

所以,我的问题是:

这个查询应该花这么长时间吗?我应该使用其他网格尺寸吗?该过滤器表达式是什么意思?

有人有优化这个的提示吗?

4

2 回答 2

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]
于 2016-03-23T20:30:09.547 回答
1

简而言之,您正在使用参数 t2.Geo 调用函数,该函数必须由函数评估 t2 中 t2.ObjecttypeId = 1 和 t2.CompanyId = 3 的所有值。在表 t2 上创建索引不会t 真的很有帮助,因为它不能使用那些预先计算的索引值。相反,它必须首先对 t2 中的所有值运行函数 t1.Geo.STIntersects(t2.Geo) - 这与预先计算的索引值几乎没有关系。

如果速度是您的目标并且您拥有存储空间,则可以创建第三个表,其中包含预先计算的 t1.Geo.STIntersects(t2.Geo) 的每个组合的结果。然后,您可以将 t1 和 t2 连接到第三个表中的预计算值,这应该能够产生几乎即时的查询结果(对于具有 1,529 和 22,000 条记录的源表)。

如果 t1 和 t2 中的数据相对静态,您可以手动重新运行查询以更新第三个表中的数据。如果它经常更改,它可以通过对 t1 和 t2 的更新、插入和删除触发器自动维护,或者您可以将更新、插入和删除包装到更新预计算表的存储过程中。

于 2012-08-30T17:44:46.430 回答