SQL WHERE句の短絡は評価されますか?


142

SQL WHERE句のブール式は短絡評価され ますか?

例えば:

SELECT * 
FROM Table t 
WHERE @key IS NULL OR (@key IS NOT NULL AND @key = t.Key) 

場合@keyがNULL IS TRUEと評価、さ@keyがNULLでなく、@key = t.Key評価済み?

いいえの場合、なぜですか?

はいの場合、保証されますか?ANSI SQLの一部ですか、それともデータベース固有ですか?

データベース固有の場合、SqlServer?Oracle?MySQL?


@key IS NOT NULL句は冗長ではありませんか?LHSの@key IS NULL句はこのnoを処理しますか?
消費者、2009

10
@splender-質問への回答によって異なります
グレッグディーン

@グレッグ:私は消費者に同意します。短絡の欠如や存在が違いを生むのはわかりません。@keyがNULLの場合、@ key = t.Keyは常にfalseを返します。NULL!= NULLだからです(結局、IS NULLを使用するのはそのためです)。
マイケル・マドセン

14
@Michaelと@spender-問題のポイントは、2番目の条件が評価されるかどうかです。問題は、この特定のSQLステートメントができるだけ少ない文字数で記述されていることではありません。より複雑な例では、where句が短絡するかのように、間違いなく問題となる式を書くことができるので、間違いなく問題になります。
グレッグ・ディーン、

2
短絡は、条件を左から右に評価することを意味します。WHERE a = 1 AND b = 2データベースエンジンが最初にb = 2であるすべての行を見つけることが効率的であるような条件が与えられた場合、a = 1でフィルタリングします。保証を要求すると、オプティマイザは役に立たなくなります。
Salman A

回答:


72

ANSI SQL Draft 2003 5WD-01-Framework-2003-09.pdf

6.3.3.3ルール評価順序

[...]

優先順位が形式または括弧によって決定されない場合、式の効果的な評価は一般的に左から右に実行されます。ただし、式が実際に左から右に評価されるかどうか、特にオペランドまたは演算子によって条件が発生する可能性がある場合、または式のすべての部分を完全に評価せずに式の結果を決定できるかどうかは、 実装に依存します


4
実装依存?すごい。知っておくと良い。少なくともCASE短絡しています。
ダカブ2015年

3
これは、式の評価が不明確であることを意味しませんか?「(0 = 0 OR NULL)」は、すべての項が評価される場合は常にNULLですが、左から右に評価されて短絡されている場合は常にtrueです。
user48956 2016

6
SQLは宣言型言語であり、基本的には制御フローを記述せずに計算のロジックを表現します。これは、短絡評価の必須スタイルとその結果に矛盾します。
ホルヘガルシア

私はそれについて@JorgeGarciaのように考えていませんでした。ショートサーキット評価は、暗黙的に操作の命令を強制していると思います。私はこれが微妙な問題の根本である可能性があるいくつかのコードと取り組んでいます。洞察をありがとう。
カルノーアントニオロメロ

58

上記から、短絡は実際には利用できません。

必要な場合は、Caseステートメントをお勧めします。

Where Case when Expr1 then Expr2 else Expr3 end = desiredResult

Expr1常に評価されますが、のうちの1つにすぎないExpr2Expr3、行ごとに評価されます。


3
それは、私が想定しているRDBMSの実装によって異なります。少なくともSQL Serverの場合、この動作(つまり、短絡)を示さないことが文書化されている例外が少なくとも1つ存在します。cf CASE(Transact-SQL)-備考。私はこの質問でこのケースを引用しました。SQL-WHERE条件の明示的な順序?
TT。

1
ステートメントではなく、ケース
jarlh

19

これは、3つの理由で、ショートしないように書いた場合の1つだと思います。

  1. MSSQLの場合、明白な場所でBOLを見ても解決されないので、私にとっては、それは標準的にあいまいです。

  2. 少なくとも私は私のコードが機能することを知っているからです。さらに重要なことは、私の後に来る人も同じように、同じ質問を何度も繰り返して心配するように設定しないことです。

  3. いくつかのDBMS製品について十分な頻度で書いていますが、それらを簡単に回避できるのであれば、違いを覚える必要はありません。


4
素晴らしい提案。それは質問には答えませんが、それは素晴らしい実用的な見方です。そう+1
グレッグディーン

12

SQL Server(2005)での短絡が保証されているとは思いません。SQL Serverは、多くのこと(インデックス、統計、テーブルサイズ、リソースなど)を考慮した最適化アルゴリズムを通じてクエリを実行し、効果的な実行計画を作成します。この評価の後では、短絡ロジックが保証されているとは言えません。

私はいつの日か同じ質問に出くわしましたが、私の研究では決定的な答えは得られませんでした。小さなクエリを記述して、それが機能することの証拠を与えることができますが、データベースの負荷が増加するにつれて、テーブルが大きくなり、データベース内で物事が最適化されて変更されることを確信できますか?ホールド。私は注意を怠ることができなかったため、短絡を確実にするためにWHERE句でCASEを使用しました。


7

データベースの仕組みを覚えておく必要があります。パラメータ化されたクエリが与えられると、dbはそのクエリに基づいて、パラメータの値なしで実行プランを構築します。このクエリは、実際に提供される値に関係なく、クエリが実行されるたびに使用されます。クエリが特定の値で短絡するかどうかは、実行プランには関係ありません。


6
実行速度が重要です!
user4951 2011

それが現在機能しているからといって、変更できないわけではありません。モデル/セマンティクスを実装から分離する必要があります。実行プランはクエリの実行を最適化するために内部的に実装されています...短絡セマンティクスはSQLの宣言的な性質に矛盾するだけでなく、そのような最適化を制約する可能性があります。ただし、DBMSで短絡評価セマンティクスがサポートされる場合、そのようなセマンティクスをサポートするように実行プランの実装が変更されます。
ホルヘガルシア

3

通常、これはオプションのパラメーターに使用します。これは短絡と同じですか?

SELECT  [blah]
FROM    Emp
WHERE  ((@EmpID = -1) OR (@EmpID = EmpID))

これにより、属性のオプションのチェックを説明するために、-1または何でも渡すオプションが与えられます。これには、複数のテーブル、またはできればビューの結合が含まれる場合があります。

非常に便利ですが、dbエンジンに追加の作業を行うことは完全にはわかりません。


2

SQL Serverの場合、バージョンに依存すると思いますが、SQL Server 2000での私の経験では、@ keyがnullの場合でも@key = t.Keyを評価します。つまり、WHERE句を評価するときに効率的な短絡は行われません。

ユーザーがさまざまな基準を入力したり入力したりできない柔軟なクエリを実行する方法として、この例のような構造を推奨する人を見てきました。私の観察では、@ keyがnullの場合でもKeyはクエリプランに含まれており、Keyにインデックスが付けられている場合、効率的にインデックスを使用しません。

さまざまな基準を持つこの種の柔軟なクエリは、おそらく動的に作成されたSQLが本当に最善の方法です。@keyがnullの場合は、単にそれをクエリに含めないでください。


2

ちょうどこの質問に出くわしました、そしてすでにこのブログエントリーを見つけました:http : //rusanu.com/2009/09/13/on-sql-server-boolean-operator-short-circuit/

SQLサーバーは、適切と思われる場所であればどこでもクエリを自由に最適化できるため、ブログ投稿の例では、短絡に頼ることはできません。

ただし、CASEは文書化された順序で評価するように文書化されているようです。そのブログ投稿のコメントを確認してください。


1

短絡評価の主な特徴は、結果が決定されるとすぐに式の評価を停止することです。つまり、評価されるかどうかに関係なく結果は同じになるため、式の残りの部分は無視できます。

二項ブール演算子は計算可能です。つまり、

a AND b == b AND a
a OR  b == b OR  a
a XOR b == b XOR a

そのため、評価の順序に関する保証はありません。評価の順序は、クエリオプティマイザーによって決定されます。

オブジェクトを持つ言語では、短絡評価でのみ評価できるブール式を記述できる場合があります。サンプルコードの作成は、このような言語(C#、Delphi、VB)でよく使用されます。例えば:

if(someString == null | someString.Length == 0 )
  printf("no text in someString");

場合は、このC#の例は、例外が発生しますsomeString == null、それは十分に評価されますので。短絡評価では毎回動作します。

SQLは、初期化解除できないスカラー変数(オブジェクトなし)でのみ動作するため、評価できないブール式を記述する方法はありません。NULL値がある場合、比較はfalseを返します。

つまり、SQLでは、短絡または完全評価の使用に応じて評価が異なる式を記述できません。

SQL実装が短絡評価を使用する場合、うまくいけばクエリの実行速度が上がるだけです。


1
はい、ブール演算子は可換です。オブジェクトはそれとは関係がないと思います。
グレッグディーン

1

ショートサーキットについては知りませんが、if-elseステートメントとして記述します

if (@key is null)
begin

     SELECT * 
     FROM Table t 

end
else
begin

     SELECT * 
     FROM Table t 
     WHERE t.Key=@key

end

また、変数は常に方程式の右辺になければなりません。これにより、検索が可能になります。

http://en.wikipedia.org/wiki/Sargable


1
誰かが右側の変数についてそれを裏付けることができますか?どういうわけか、私はそれを信じるのに苦労しています。
グレッグディーン

searchoracle.techtarget.com/expert/KnowledgebaseAnswer/… 現在、他に多くを見つけることができません
DForck42 '27

私は記事を理解しています。これは、検索可能でない列名の関数について話しています。分かりました。ただし、(A = @a)または(@a = A)の問題は考えません。
グレッグディーン

私は間違っているかもしれません。それがまだ存在しない場合は、良い質問かもしれません。
DForck42 2009

1

SQL Server 2008 R2での簡単なテストの下:

SELECT *
FROM table
WHERE 1=0
AND (function call to complex operation)

これは、レコードなしですぐに戻ります。一種の短絡動作が見られました。

次にこれを試しました:

SELECT *
FROM table
WHERE (a field from table) < 0
AND (function call to complex operation)

どのレコードもこの条件を満たすことを知らない:

(a field from table) < 0

これには数秒かかり、短絡動作がなくなり、すべてのレコードについて複雑な操作が評価されていたことを示しています。

これがみんなに役立つことを願っています。


1
私の推測では、最初のクエリは、計画の実行が実際に開始される前に、コンパイル時に「ショートサーキット」でした。
Louis Somers

1

MySQLがWHERE句のショートサーキットを実行することを証明するデモがあります

http://rextester.com/GVE4880

これにより、次のクエリが実行されます。

SELECT myint FROM mytable WHERE myint >= 3 OR myslowfunction('query #1', myint) = 1;
SELECT myint FROM mytable WHERE myslowfunction('query #2', myint) = 1 OR myint >= 3;

これらの唯一の違いは、OR条件でのオペランドの順序です。

myslowfunction意図的に1秒間スリープし、実行されるたびにログテーブルにエントリを追加するという副作用があります。上記の2つのクエリを実行したときにログに記録される結果は次のとおりです。

myslowfunction called for query #1 with value 1
myslowfunction called for query #1 with value 2
myslowfunction called for query #2 with value 1
myslowfunction called for query #2 with value 2
myslowfunction called for query #2 with value 3
myslowfunction called for query #2 with value 4

上記は、他のオペランドが常にtrueとは限らない場合(短絡のため)、OR条件の左側に現れるとき、スロー関数がより多く実行されることを示しています。


4
うーん、あなたが言うつもりだったのは「MySQLがこの特定のインスタンスで WHERE句のショートサーキットを実行することを証明するデモです:」
TT。

1
確かに-それはそれが起こり得ることの単なる証拠です。
スティーブチェンバーズ

0

これはクエリアナライザーで余分な4秒かかるので、IFが短絡されていないことがわかります...

SET @ADate = NULL

IF (@ADate IS NOT NULL)
BEGIN
    INSERT INTO #ABla VALUES (1)
        (SELECT bla from a huge view)
END

保証された方法があるといいですね!


-2

MS Sqlサーバーが短絡理論をサポートしていることは明らかですが、不必要なチェックを回避してパフォーマンスを向上させます。

サポート例:

SELECT 'TEST'
WHERE 1 = 'A'

SELECT 'TEST'
WHERE 1 = 1 OR 1 = 'A'

ここで、最初の例は、「varchar値「A」をデータ型intに変換するときに変換に失敗しました」というエラーになります。

条件1 = 1がTRUEと評価されたため、2番目の条件は簡単に実行され、2番目の条件はまったく実行されませんでした。

さらにもっと

SELECT 'TEST'
WHERE 1 = 0 OR 1 = 'A'

ここで、最初の条件はfalseと評価され、DBMSは2番目の条件に進み、上記の例のように変換エラーが返されます。

注:クエリの結果がエラーであり、実行された条件が短いか、それ以外の場合は、条件が実行されたか、または条件が短いかを確認するためだけに、このエラー条件を書き込みました。

簡単な説明

考えて、

WHERE 1 = 1 OR 2 = 2

最初の条件がTRUEに評価されると、2番目の条件を評価しても意味がありません。どのような値で評価しても結果にはまったく影響しないため、SQL Serverが不要な条件チェックまたは評価をスキップしてクエリ実行時間を節約できるためです。 。

以下の場合は「OR」最初の条件がに評価された場合TRUEによって接続されたチェーン全体を「OR」他人を評価せずにtrueに評価されるように考えられます。

condition1 OR condition2 OR ..... OR conditionN

condition1がtrueと評価された場合、conditionNがスキップされるまですべての条件を残ります。最初のTRUEの決定時の一般化された単語では、ORによってリンクされた他のすべての条件はスキップされます。

2番目の条件を検討する

WHERE 1 = 0 AND 1 = 1

最初の条件がFALSEと評価されているため、2番目の条件を評価しても意味がありません。どのような値で評価しても結果にはまったく影響しないため、SQL Serverが不要な条件チェックまたは評価をスキップしてクエリ実行時間を節約できるためです。 。

以下の場合には「AND」第一の条件は、と評価された場合にFALSEに接続されたチェーン全体「AND」他人を評価することなく、FALSEに評価されると考えられます。

condition1 AND condition2 AND ..... conditionN

condition1がFALSEと評価された場合conditionNがスキップされるまですべての条件を残ります。最初のFALSEの決定時の一般化された単語では、ANDによってリンクされた他のすべての条件はスキップされます。

したがって、賢明なプログラマーは常に、費用がかからないか、または最も少ない条件が最初に評価されるような条件のチェーンをプログラムするか、または短絡の利益を最大にすることができるような条件を整える必要があります


反対票を投じる理由:現実のデータを使用して、実際のサーバーで常にテストします。以前のコメントが食べられたようです。
ジャスミン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.