【发布时间】:2010-11-19 14:40:19
【问题描述】:
如果WHERE 子句包含一个常量,我有一个递归查询,它执行得非常快,但如果我用具有相同值的参数替换该常量,它会变得非常慢。
查询 #1 - 使用常量
;WITH Hierarchy (Id, ParentId, Data, Depth)
AS
( SELECT Id, ParentId, NULL AS Data, 0 AS Depth
FROM Test
UNION ALL
SELECT h.Id, t.ParentId, COALESCE(h.Data, t.Data), Depth + 1 AS Depth
FROM Hierarchy h
INNER JOIN Test t ON t.Id = h.ParentId
)
SELECT *
FROM Hierarchy
WHERE Id = 69
查询 #2 - 带参数
DECLARE @Id INT
SELECT @Id = 69
;WITH Hierarchy (Id, ParentId, Data, Depth)
AS
( SELECT Id, ParentId, NULL AS Data, 0 AS Depth
FROM Test
UNION ALL
SELECT h.Id, t.ParentId, COALESCE(h.Data, t.Data), Depth + 1 AS Depth
FROM Hierarchy h
INNER JOIN Test t ON t.Id = h.ParentId
)
SELECT *
FROM Hierarchy
WHERE Id = @Id
如果表有 50,000 行,带有常量的查询运行 10 毫秒,带有参数的查询运行 30 秒(慢 3,000 倍)。
将最后一个WHERE 子句移动到递归的锚定义不是一个选项,因为我想使用查询来创建一个视图(没有最后一个WHERE)。视图中的选择将具有 WHERE 子句 (WHERE Id = @Id) - 由于 Entity Framework,我需要它,但这是另一回事。
任何人都可以建议一种方法来强制查询 #2(使用参数)使用与查询 #1(使用常量)相同的查询计划吗?
我已经尝试过使用索引,但没有帮助。
如果有人愿意,我也可以发布表定义和一些示例数据。 我正在使用 SQL 2008 R2。
提前感谢您的帮助!
执行计划 - 查询 #1 - 带有常量
执行计划 - 查询 #2 - 带参数
【问题讨论】:
-
请检查新添加的执行计划。
-
看起来好的计划将谓词推得更远了。类似于本文第二部分讨论的问题jahaines.blogspot.com/2010/03/…
-
你说得对,我只是想“下推谓词”。创建一个用户定义的表值函数和 CROSS APPLY 解决了我的问题,谢谢!
标签: sql sql-server-2008 where-clause