我有一个存储过程,需要一秒钟才能正常运行。用户想要该查询中另一个表的数据,所以我将这些数据合并到一个UNION ALL和新表中缺少的一堆虚拟列中。
它在测试中运行良好,但是当我们将它部署到SQL 2000 Server时,它开始超时。旧查询在一秒钟内运行,2个新查询都在一秒钟内运行,但是当它们使用UNION ALL组合时,查询超时。
以下是查询外观的一般概念。真正的查询有大约20个输入参数,并返回大约30或40列,但这应该给出基本的想法:
CREATE PROCEDURE dbo.SearchHistory
(
@Criteria1 bigint,
@Criteria2 int,
@Criteria3 varchar(10)
)
AS
BEGIN
-- Part 1
SELECT
A,
NULL AS B,
0 AS C,
D
FROM TableA
WHERE @Criteria1 IS NULL
AND @Criteria3 IS NULL
AND (A = @Criteria2 OR @Criteria2 IS NULL)
UNION ALL
-- Part 2
SELECT
A,
NULL AS B,
0 AS C,
E
FROM TableA
WHERE @Criteria1 IS NULL
AND @Criteria3 IS NULL
AND (A = @Criteria2 OR @Criteria2 IS NULL)
UNION ALL
-- Part 3
SELECT
A,
B,
C,
D
FROM TableB
WHERE (F = @Criteria1 OR @Criteria1 IS NULL)
AND (A = @Criteria2 OR @Criteria2 IS NULL)
AND (G = @Criteria3 OR @Criteria3 IS NULL)
END
在上面的示例中,@ Criteria1不为null,因此第1部分和第2部分将返回0行,第3部分仅返回3行。但如果我评论第1部分和第2部分,它会立即完成;如果我让他们进去,我会暂停
如何说服SQL Server在这种情况下不要乱用它的执行计划?
答案 0 :(得分:3)
我认为你的问题是因为SQL Server的参数嗅探。
http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/
http://blogs.msdn.com/b/queryoptteam/archive/2006/03/31/565991.aspx
我遇到过好几次。它有几种方法。例如。使用WITH RECOMPILE作为@Biff MaGriff建议。我发现修复的最简单方法是将所有输入参数转换为本地参数,并使用本地参数。
答案 1 :(得分:0)
如果没有看到执行计划,就无法回答这个问题(请将它们作为图像发布,每个部分一个,联合查询一个)。解决方法是使用临时表,在其中单独插入部件。然而,更好的解决方案是首先修复查询。