通常の実行に 1 秒もかからないストアド プロシージャがあります。ユーザーはそのクエリで別のテーブルのデータを求めていたので、そのデータを UNION ALL と、新しいテーブルに欠けていたダミー列の束とマージしました。
テストでは問題なく動作しましたが、SQL 2000 Server に展開すると、タイムアウトが発生し始めました。古いクエリは 1 秒未満で実行され、2 つの新しいクエリは両方とも 1 秒未満で実行されますが、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 が実行計画を台無しにしないようにするにはどうすればよいでしょうか?