Zol*_*tan 11 sql where-clause sql-server-2008
我有一个递归查询,如果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
Run Code Online (Sandbox Code Playgroud)
查询#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
Run Code Online (Sandbox Code Playgroud)
对于具有50,000行的表,具有常量的查询运行10毫秒,具有该参数的查询运行30秒(慢3000倍).
将最后一个WHERE子句移动到递归的锚定义不是一个选项,因为我想使用查询来创建一个视图(没有最后一个WHERE).视图中的选择将具有WHERE子句(WHERE Id = @Id) - 因为实体框架我需要这个,但这是另一个故事.
任何人都可以建议一种方法来强制查询#2(使用参数)使用与查询#1相同的查询计划(使用常量)?
我已经尝试过使用索引,但这并没有帮助.
如果有人想我可以发布表定义和一些示例数据.我正在使用SQL 2008 R2.
提前谢谢你的帮助!
执行计划 - 查询#1 - 使用常量

执行计划 - 查询#2 - 带参数

正如Martin在问题中的评论中所建议的那样,问题是SQL服务器没有正确地推断WHERE子句中的谓词 - 请参阅他的评论中的链接.
我最终创建了一个用户定义的表值函数,并将其与CROSS APPLY运算符一起用于创建视图.
让我们看看解决方案本身.
用户定义的表值函数
CREATE FUNCTION [dbo].[TestFunction] (@Id INT)
RETURNS TABLE
AS
RETURN
(
WITH
Hierarchy (Id, ParentId, Data, Depth)
AS(
SELECT Id, ParentId, NULL AS Data, 0 AS Depth FROM Test Where Id = @Id
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
)
Run Code Online (Sandbox Code Playgroud)
视图
CREATE VIEW [dbo].[TestView]
AS
SELECT t.Id, t.ParentId, f.Data, f.Depth
FROM
Test AS t
CROSS APPLY TestFunction(Id) as f
Run Code Online (Sandbox Code Playgroud)
用常量查询
SELECT * FROM TestView WHERE Id = 69
Run Code Online (Sandbox Code Playgroud)
使用参数查询
DECLARE @Id INT
SELECT @Id = 69
SELECT * FROM TestView WHERE Id = @Id
Run Code Online (Sandbox Code Playgroud)
使用parmater的查询基本上与使用常量的查询一样快.
感谢Martin和其他人!
| 归档时间: |
|
| 查看次数: |
9311 次 |
| 最近记录: |