SQL 2000 UNION ALL废墟查询优化

Bry*_*ner 5 sql-server query-optimization union-all

我有一个存储过程,需要一秒钟才能正常运行.用户需要来自该查询中另一个表的数据,因此我将该数据与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
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,@ Criteria1不为null,因此第1部分和第2部分将返回0行,第3部分仅返回3行.但如果我评论第1部分和第2部分,它会立即完成; 如果我让他们进去,我会暂停

你如何说服SQL Server在这样的情况下不要乱用它的执行计划?

Bla*_*zes 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

我已经遇到过好几次了。有几种方法可以解决这个问题。例如,按照@Biff MaGriff 建议使用WITH RECOMPILE。我发现修复的最简单方法是将所有输入参数转换为本地参数,并使用本地参数。