SQLではwhere句の順序は重要ですか?


121

PEOPLE3つのカラムを持つというテーブルがあるとしましょうID, LastName, FirstName。これらのカラムにはインデックスが付けられていません。
LastNameよりユニークで、FirstNameそれほどユニークではありません。

2つの検索を行う場合:

select * from PEOPLE where FirstName="F" and LastName="L" 
select * from PEOPLE where LastName="L" and FirstName="F"

私の考えでは、よりユニークな基準(LastName)がwhere句の最初に来るため、2番目の方が速く、レコードがより効率的に排除されると考えています。オプティマイザーは最初のSQLを最適化するほど賢いとは思いません。

私の理解は正しいですか?


8
いいえ、その順序は重要ではありません。適切なクエリオプティマイザーはすべてのWHERE句を調べ、そのクエリを満たすための最も効率的な方法を
見つけ

3
これらの2つのステートメントを実行したときの観察は何でしたか?実行計画はどのように見えましたか?
コンラッドフリックス

3
特定のRDBMSを参照していますか?確かに違いがあります。
Bjoern


回答:


101

いいえ、その順序は関係ありません(または少なくとも:関係ありません)。

適切なクエリオプティマイザーは、句のすべての部分を調べ、WHEREそのクエリを満たすための最も効率的な方法を見つけます。

SQL Serverクエリオプティマイザーが適切なインデックスを選択することは知っています。2つの条件がどの順序であるかに関係なく、他のRDBMSでも同様の戦略があると思います。

重要なのは、これに適したインデックスがあるかどうかです。

SQL Serverの場合、次の場合にインデックスを使用する可能性があります。

  • 上のインデックス (LastName, FirstName)
  • 上のインデックス (FirstName, LastName)
  • just (LastName)、またはjust (FirstName)(または両方)のインデックス

一方、SQL Serverの場合も同様に、テーブルからすべてのSELECT *を取得するために使用し、テーブルがかなり小さい場合、クエリオプティマイザーが使用する代わりにテーブル(またはクラスター化インデックス)スキャンを実行する可能性が高くなります。インデックス(他のすべての列を取得するための完全なデータページへのルックアップは非常に高速になるため)


インデックスがない場合は、データによっては、演算が正しい可能性があります。インデックスなしでこのように冷静に行うコースは、奇妙な決断です...
トニーホプキンソン

@TonyHopkinson:私はそうは思いません-インデックスがなくても、まったく違いがあるとは思えません。結局のところ、インデックスがなければ、RDBMSは実際に全テーブルスキャン以外に何ができますか?
marc_s

2
SQLサーバーとの興味深いサイドノート、明らかに述語内に存在しないため、実際に計画の作成に影響することができますbradsruminations.blogspot.com/2010/04/looking-under-hood.html
ジャスティンSwartsel

3
奇妙なことに、クエリの最初の実行では、WHERE句の条件の順序が重要です!次のような2つの条件WHERE T1.col_1/T2.col_2 > 10 AND T2.col_2 <> 0がありDIVIDE BY 0ました。エラーが発生しました。順序を切り替えた後、クエリが正常に実行された条件。次に、もう一度エラーが発生すると予想されるように順序を切り替えましたが、今度はうまくいきました!オプティマイザー/実行計画がそれを処理するため、問題ではありません
Radu Gheorghiu

1
私はあなたが言ったのが好きです、「...または少なくとも:問題ではない」-私は完全に同意します。残念ながら、時にはそれが問題になります。SQLがオプティマイザで処理するには複雑すぎて、列の順序やテーブルの結合順序などの違いがあった場合を見てきました。RDBMS、SQLステートメントの複雑さ、さらにはリリースによって異なります。SQLが非常に複雑な場合、オプティマイザの判断が不適切になったり、オプティマイザコードでハードコードされたデフォルトが使用されたりする可能性があります。
ビクター

19

WHERE句の順序は、SQL標準に準拠しているデータベースでは違いがありません。ほとんどのデータベースでは、評価の順序は保証されていません。

SQLが順序を気にするとは思わないでください。次の場合、SQL Serverでエラーが発生します。

select *
from INFORMATION_SCHEMA.TABLES
where ISNUMERIC(table_name) = 1 and CAST(table_name as int) <> 0

この句の最初の部分が最初に実行された場合、数値のテーブル名のみが整数としてキャストされます。ただし、失敗し、SQL Server(他のデータベースと同様)がWHEREステートメントの句の順序を気にしないという明確な例が提供されます。


エラーを引き起こしているそのクエリは、WHERE述語評価の順序と何が関係していますか?
ジム

7
@Jim ISNUMERIC(table_name) = 1最初に評価された場合CAST、数値のテーブル名に対してのみ呼び出されます。ただし、最初にCAST評価されないため、数値以外のテーブル名についても評価され、エラーメッセージが表示されます。
hibbelig 2013

2
明確な説明
neeohw 2017

条件を交換するとSQLサーバーで逆の処理が行われるかどうかを確認しましたが、どちらの方法でも失敗します。これは、(1)最適化されていない、または(2)コンパイル時のエラーであり、SQLが何も比較しようとせず、予備的な処理を行わないことのいずれかを意味していると思います。私の推測では、これはnrです。2.
Louis Somers

9

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

6.3.3.3ルール評価順序

...

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

ここからコピー


2

いいえ、すべてのRDBMはまずクエリを分析して開始し、where句を並べ替えて最適化します。

使用しているRDBMに応じて、分析の結果を表示できます(たとえば、OracleでExplain Planを検索してください)。

M.


それはインデックスに基づいて行われます。したがって、コンテンツに関しては間接的です。
トニーホプキンソン

1

元のOPステートメント

私の考えでは、より一意の基準(LastName)がwhere句で最初に来るため、2番目の方が速く、レコードがより効率的に排除されると考えています。>オプティマイザーは最初のSQLを最適化するのに十分スマートではないと思います。

2番目に選択性の高い列よりも最初に選択性の高い列を配置する必要があるインデックスを作成するときに、列の順序を選択することとこれを混同していると思います。

ところで、上記の2つのクエリでは、SQLサーバーオプティマイザーは最適化を行いませんが、トリビラプランを使用します。


0

名前にインデックスが付けられていないと仮定すれば、それは事実です。ただし、データが異なると誤りになります。毎回異なる可能性のある方法を見つけるために、DBMSは列ごとに個別のカウントクエリを実行して数値を比較する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.