我有一个存储过程,它需要不到一秒钟的时间才能正常运行。用户想要该查询中另一个表中的数据,因此我将该数据与 UNION ALL 和新表中缺少的一堆虚拟列合并。
它在测试中运行良好,但是当我们将它部署到 SQL 2000 服务器时,它开始出现超时。旧查询在一秒钟内运行,两个新查询都在一秒钟内运行,但是当它们使用 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 不为空,因此第 1 部分和第 2 部分将返回 0 行,而第 3 部分仅返回 3 行。但是如果我注释掉第 1 部分和第 2 部分,它会立即结束;如果我把它们留在里面,我会超时。
在这种情况下,你如何说服 SQL Server 不要乱搞它的执行计划?