0

次のような sql ステートメントがあり、変数 @FOO がコードのどこかに設定されているとします。

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(FIELD = @FOO OR @FOO IS NULL)

クエリ オプティマイザーは、最初に OR の 2 番目の側 (@FOO IS NULL) を実行するほどスマートですか? (別の仮定) フィールド比較を行うよりも null チェックを行う方が速いためですか?

私はいくつかの非公式のベンチマークを行いましたが、違いが見られないだけでなく、試行で異なる結果時間が得られ、適切な比較を行うことができなくなりました。

4

5 に答える 5

3

短い答えは...

はい、オプティマイザーは十分にスマートです。

長い答え...

SQL は命令型ではなく宣言型です: クエリは、結果が満たさなければならない基準の記述であり、それらの結果を生成する方法についての段階的な指示ではありません。

オプティマイザーは、最も効率的な順序でクエリを実行します。句を特定の順序で評価すること、またはそれらをまったく評価することを保証するものではありません。特定の句を評価せずに正しい結果を得ることができるのであれば、なぜわざわざするのでしょうか?

特定のクエリの実際の評価順序は実装の詳細であり、時間の経過とともに変化する可能性があります (たとえば、テーブルの統計が変化するなど)。

実際には、オプティマイザーは時折間違ったことをしますが、この特定のケース (変数を NULL とテーブルまたはインデックスからの読み取りと比較する場合) では、失敗する可能性はあまりないと思いますが、使用を検討することをお勧めします。OPTION(RECOMPILE)またはOPTION(OPTIMIZE FOR ...)

于 2009-02-12T23:54:50.340 に答える
1

私の経験では、「OR」句の代わりに 2 つのクエリと「UNION」を使用する方が高速な場合があります。

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(FIELD = @FOO)

UNION

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(@FOO IS NULL)

このアプローチには、SELECT ステートメントが重複するという欠点がありますが、パフォーマンスが 1500% 向上したため、それが正当化されました。もちろん、これはデータベースの構造に依存します (私の場合はかなり悪く、変更できませんでした)。

于 2009-02-13T10:23:51.857 に答える
1

逆の順序で句を使用してテストしてみてください。

SELECT FIELDLIST 
FROM TABLE 
WHERE 
(@FOO IS NULL OR FIELD = @FOO)

最初のテストで 2 番目のテストがショートすることがありますが、その逆はありません。

于 2009-02-12T18:15:57.987 に答える
0

このクエリがsproc内にある場合、ここで関係している可能性のある1つの要因は、「パラメータスニッフィング」です。これにより、クエリの応答時間が一貫しなくなる可能性があります。これを修正するには、sprocで内部変数を宣言し、この変数をパラメーター値に割り当ててから、where句で内部変数を使用するか、 sprocでRECOMPILE句を使用します。このテーマに関する多くのリンクがあります。

于 2009-02-12T18:29:07.067 に答える
0

一般的なケースでどちらの比較が高速になるかを判断できると仮定すると、最初に高速な条件を適用するのに十分スマートです。この場合、NULL チェックはほとんどの場合、式の両側から最大 1 バイトを比較する必要があり、それを因数分解できるため、より高速です。

于 2009-02-12T18:14:51.763 に答える