【问题标题】:How can I speed up this Sql Server Spatial query? [closed]如何加快此 Sql Server 空间查询? [关闭]
【发布时间】:2011-03-22 00:38:49
【问题描述】:

我有(我认为)是一个简单的 Sql Server 空间查询:

抓取存在于某个 4 边多边形内的所有美国州(即网页的 google/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 / Grids 设置不正确(我真的不知道应该将这些值设置为什么,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?其他人知道为什么吗?我是否还需要为此发布查询计划以帮助解释原因/内容?

【问题讨论】:

    标签: sql-server-2008 performance spatial spatial-index


    【解决方案1】:

    您似乎有一个运行查询的最佳计划。这将很难改进。以下是一些观察结果。

    查询正在对 PK_States 索引执行聚集索引扫描。它没有使用空间索引。这是因为查询优化器认为使用聚集索引而不是任何其他索引会更好。为什么?可能是因为 States 表中的行数很少(华盛顿特区、波多黎各等地可能还有 50 行以上)。

    SQL Server 在 8KB 页面上存储和检索数据。过滤操作的行大小(请参阅 Estimate Row Size)为 8052 字节,这意味着每页有一行,整个表大约有 50 页。查询计划估计它将处理其中大约 18 行(请参阅估计的行数)。这不是要处理的大量行。我的解释没有针对表格中的额外页面,但重点是这个数字大约是 50 页,而不是 50,000 页。

    所以,回到为什么它使用 PK_States 索引而不是 SPATIAL_States_Boundry 索引。根据定义,聚集索引包含表的实际数据。非聚集索引指向数据所在的页面,因此需要检索的页面更多。所以,非聚集索引只有在数据量大的时候才有用。

    您可以采取一些措施来减少页面进程的数量(例如,使用覆盖索引),但您当前的查询已经得到了很好的优化,您不会看到太多的性能提升。

    【讨论】:

    • 为详细的回复干杯。我真的真的很感激它:) 还有几个问题:如果查询优化器决定使用聚集索引-kewl。你是对的.. 该表中只有大约 56 行左右。那么为什么要花这么长时间呢?还有什么我可以看到吞吐量受到影响的地方:(如果不是查询..还能是什么?(顺便说一句,服务器没有以 100% 运行)。
    • 我还更新了最初的帖子,提供了更多信息……在底部的 EDIT/UPDATE 下。可以再读一遍吗?
    • 这很有趣,空间索引的效果如此之好。我怀疑使用聚集索引评估空间条件的性能不如使用空间索引快。出于测试目的,您可以在非空间列上尝试非聚集索引并运行使用该列的查询。然后,查看该查询与您之前的查询相比如何。看看没有空间逻辑的查询如何执行会很有趣。
    【解决方案2】:

    试试这个,没有索引提示:

    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 查询(或使用您自己存储的 以空间值为 参数)以确保查询成本 “知道”参数值 创建查询计划的时间,即 是,在批次开始时或 进入存储过程或 sp_executesql。

    【讨论】:

    • 很有趣...所以我将它移动到存储过程中,并传入了 boundingBox 变量。现在是 9 秒,没有使用 INDEX。这是在 SQL 2008 R2 / 10.50 RTM 上。
    • 另外,在 SSMS 中运行它(如上)在 9 秒内返回,没有使用索引,并将该代码放在上面,放入存储的 proc 中,并传入 BoundingBox 变量,同样如此。 :(
    • 这很有趣。如果你还没有玩过,你也可以玩 w./.Filter()。我经常发现自己在临时表中具体化了.Filter() 的结果,然后在此基础上进行更精确的操作。
    • 另外,我建议在social.msdn.microsoft.com/Forums/en-US/sqlspatial 交叉发布。对于 SQL Server 空间问题,那里的读者群比 SO 要好得多。
    猜你喜欢
    • 1970-01-01
    • 2022-01-19
    • 2015-07-02
    • 1970-01-01
    • 2023-02-11
    • 2022-10-05
    • 2018-07-03
    • 2012-08-23
    • 1970-01-01
    相关资源
    最近更新 更多