5

通常の実行に 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 が実行計画を台無しにしないようにするにはどうすればよいでしょうか?

4

2 に答える 2

3

あなたの問題はSQLServerのパラメータスニッフィングが原因だと思います。

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が提案したように、WITHRECOMPILEを使用します。私が修正するのに見つけた最も簡単な方法は、すべての入力パラメーターをローカルパラメーターに変換し、ローカルパラメーターを使用することです。

于 2011-05-19T08:09:44.097 に答える
0

これは、実行計画を見ないと答えられません (各パーツに 1 つずつ、ユニオン クエリに 1 つずつ、画像として投稿してください)。回避策は、パーツを個別に挿入する一時テーブルを使用することです。ただし、より良い解決策は、最初にクエリを修正することです。

于 2011-05-21T12:26:03.290 に答える