【发布时间】:2017-08-31 09:12:32
【问题描述】:
我有一个包含位置信息的表 (Location_Tree),以 Id/ParentId 结构排列在多个级别上,从“世界”的第 0 级一直到各个城市,通过世界地区、国家、州、县、州和城市。我们有另一个事件表,其中有一列“CreatedWithLocationId”,表示事件的位置,但没有说明所提供的位置是城市、县、国家还是其他 - 换句话说,准确性是不确定的。
我正在使用查询来制作一份报告,该报告获取一个事件的位置并显示“附近”列出的其他事件。最佳匹配将是与输入位置共享位置的那些,但如果找不到足够的匹配,我将“缩小”该位置,在树上搜索父位置,直到找到足够的匹配报告要求.
为了实现这一点,我做了一个递归 CTE,它将从 Location_Tree 表中获取给定位置的所有子节点。因此,我获取输入位置,找到 parentId,然后找到共享该 parentId 的所有位置,或者将其作为祖父母等,根据需要按级别限制等等。
DECLARE @Ancestor_Id INT = 1;
WITH Location_Children AS
(
SELECT @Ancestor_Id AS Id, NULL AS ParentId
UNION ALL
SELECT
B.Id, B.ParentId
FROM Location_Tree AS B
INNER JOIN Location_Children AS C ON B.ParentId = C.Id
)
SELECT * FROM Location_Children;
即使返回的唯一行是@Ancestor_Id AS Id, NULL AS ParentId 行,上述查询总是会导致对Location_Tree 表() 的主键的聚集索引扫描和急切假脱机——所有大量行参与执行计划,查询大约需要15秒完成,返回我的一行。
有人对我如何加快速度有任何建议吗?我已经尝试添加索引等,我有点不愿意进行大规模查询以使用 CASE 语句或一系列左连接来替换 CTE,因为这需要大量的脚本编写......我已经尝试了这个查询的每一种排列方式,使用内联函数、自定义表数据类型、(几乎)一切都无济于事......接下来我应该尝试什么?
【问题讨论】:
-
您的执行计划似乎与您的示例代码不匹配。使用Paste The Plan @ brentozar.com 分享您的执行计划,以下是说明:How to Use Paste the Plan。
-
@SqlZim 感谢您提供的信息;我已更新问题以包含新创建的链接。
-
如果你能告诉我 Eager Spool 的成本百分比,我或许可以回答这个问题。前几天我在递归 CTE 中遇到了类似的问题,不得不寻找涉及该运算符的解决方法,结果证明这是罪魁祸首。
-
@SQLServerSteve - Eager Spool 成本是执行计划的 72%,而聚集索引扫描是另外 28%
-
感谢@High Plains Grifter - 我错过了上面指向您的执行计划的链接。
标签: performance sql-server-2008 indexing sql-execution-plan recursive-query