1

SQL Server 2005 を使用しています。

このような SQL ステートメントの実行に問題があります

DECLARE @Param1 BIT
SET @Param1 = 1

SELECT 
    t1.Col1,
    t1.Col2
FROM
    Table1 t1
WHERE
    @Param1=0 OR
    (t1.Col2 in 
        (SELECT  t2.Col4
            FROM 
                Table2 t2
            WHERE 
                t2.Col1 = t1.Col1 AND 
                t2.Col2 = 'AAA' AND 
                t2.t3 <> 0)
    )

このクエリは非常に長時間実行されます。

しかし、に置き換える@Param11、クエリの実行時間は約 2 秒です。

問題を解決する方法についての情報をいただければ幸いです。

4

3 に答える 3

1

まあ、説明は十分に簡単に思えます。現在の条件@Param1=0は false (以前にパラメーターを 1 に設定) であるため、2 番目の条件を評価する必要があります。これにはサブクエリがあり、時間がかかる場合があります。最初のフィルターを に変更する@Param1=1と、それは true であり、2 番目のフィルターを評価する必要がないため、クエリが高速になります。

于 2012-11-05T14:08:37.337 に答える
0

オプティマイザーと OR ステートメントを混同しているようです。これを削除すると、SELECT ステートメントに対して 2 つの異なる実行プランが生成されることがわかります。1 つはフィルターあり、もう 1 つはフィルターなしです。

DECLARE @Param1 BIT
SET @Param1 = 1

if @Param1=0
begin
    SELECT 
        t1.Col1,
        t1.Col2
    FROM
        Table1 t1
end
else
begin
    SELECT 
        t1.Col1,
        t1.Col2
    FROM
        Table1 t1
    WHERE
        (t1.Col2 in 
            (SELECT  t2.Col4
                FROM 
                    Table2 t2
                WHERE 
                    t2.Col1 = t1.Col1 AND 
                    t2.Col2 = 'AAA' AND 
                    t2.t3 <> 0)
        )
end
于 2012-11-05T14:11:19.567 に答える
0

これは一般に N+1 問題と呼ばれます。
テーブル1で選択を行っており、見つかったレコードごとに、テーブル2で何かを探します
.@Param1を選択で決して見つからない値に設定すると、SQLエンジンはサブクエリをスキップします.
この動作を回避するには、JOIN ステートメントを使用して両方のテーブルを結合し、後で結果を where ステートメントでフィルター処理します。結合ステートメントは、2 つのテーブルを相互に照合するため、単一のサブクエリよりも少し遅くなりますが、結合を 1 回 (vs N 回) 実行するだけでよいため、パフォーマンスが大幅に向上します。
コード例:

DECLARE @Param1 BIT
SET @Param1 = 1

SELECT t1.Col1,t1.Col2
FROM Table1 t1
INNER JOIN Table2 t2 on t1.Col1 = t2.Col1
WHERE @Param1=0 
OR t2.Col2 = 'AAA' 
AND t2.t3 <> 0
于 2012-11-05T14:14:07.687 に答える