我(我认为)是一个简单的Sql Server空间查询:
抓住存在于某些4边多边形内的所有美国国家(即网页的谷歌/ bing地图的视口/边界框)
SELECT CAST(2 AS TINYINT) AS LocationType, a.Name AS FullName,
StateId, a.Name, Boundary.STAsText() AS Boundary,
CentrePoint.STAsText() AS CentrePoint
FROM [dbo].[States] a
WHERE @BoundingBox.STIntersects(a.Boundary) = 1
运行需要6秒钟:(
这是执行计划......
删除
过滤器操作的统计数据......
删除
现在,我只是不确定如何调试这个..弄清楚我需要微调等等。我有空间索引吗?我相信......
/****** Object: Index [SPATIAL_States_Boundary]
Script Date: 07/28/2010 18:03:17 ******/
CREATE SPATIAL INDEX [SPATIAL_States_Boundary] ON [dbo].[States]
(
[Boundary]
)USING GEOGRAPHY_GRID
WITH (
GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH),
CELLS_PER_OBJECT = 1024, PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF,
DROP_EXISTING = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
我是否需要提供有关返回的GEOGRAPHY
数据的更多信息?例如。分数等?或者我是否需要运行profiler
并从那里提供一些统计数据?
或者我的Cells_per_object /网格设置不正确(我真的不知道我应该将这些值设置为TBH)。
有人可以帮忙吗?请?
从@Bobs下面的第一个回复确认空间索引没有被使用,因为主键(聚簇索引)比50个奇数行的表上的非聚集索引更快...我试过强制空间索引(对于shits-n-giggles): -
SELECT CAST(2 AS TINYINT) AS LocationType, a.Name AS FullName,
StateId, a.Name, Boundary.STAsText() AS Boundary,
CentrePoint.STAsText() AS CentrePoint
FROM [dbo].[States] a WITH (INDEX(SPATIAL_States_Boundary))
WHERE @BoundingBox.STIntersects(a.Boundary) = 1
...并猜测..查询立即运行。
WTF?其他人都知道为什么?我是否还需要发布查询计划,以帮助解释原因/内容?
答案 0 :(得分:7)
您似乎有一个运行查询的最佳计划。要改善这一点很难。以下是一些观察结果。
查询正在对PK_States索引执行聚簇索引扫描。它没有使用空间索引。这是因为查询优化器认为使用聚簇索引而不是任何其他索引会更好。为什么?可能是因为州表中的行数很少(华盛顿,加州,波多黎各等地可能有50行,或者其他几行)。
SQL Server在8KB页面上存储和检索数据。过滤操作的行大小(请参阅估计行大小)为8052字节,这意味着每页有一行,整个表中有大约50页。查询计划估计它将处理这些行中的大约18行(请参阅估计的行数)。这不是要处理的大量行。我的解释没有解决作为表格一部分的额外页面,但重点是该数字大约为50而不是50,000页。
因此,回到为什么它使用PK_States索引而不是SPATIAL_States_Boundry索引。根据定义,聚簇索引包含表的实际数据。非聚集索引指向数据所在的页面,因此需要检索更多页面。因此,只有存在大量数据时,非聚集索引才会有用。
您可以采取一些措施来减少进程数量(例如,使用覆盖索引),但您当前的查询已经过很好的优化,并且您不会看到太多的性能提升。
答案 1 :(得分:2)
试试这个,w / out索引提示:
EXEC sp_executesql N'
SELECT CAST(2 AS TINYINT) AS LocationType, a.Name AS FullName,
StateId, a.Name, Boundary.STAsText() AS Boundary,
CentrePoint.STAsText() AS CentrePoint
FROM [dbo].[States] a
WHERE @BoundingBox.STIntersects(a.Boundary) = 1'
, N'@BoundingBox GEOGRAPHY', @BoundingBox
如果这有任何不同,请参阅here了解更多详情:
如果您在SSMS中运行代码, 在空间周围使用sp_executesql 查询(或使用您自己存储的 以空间值为例的程序 参数)以确保查询coster “知道”的参数值 时间创建查询计划,那 是,在批处理开始时或在 进入存储过程或 sp_executesql的。