SQL WHERE句でのINまたはOR


150

大きなデータベースを処理するとき、どちらの方がパフォーマンスが良いですか、INそれともORSQL Where句ですか?

実行方法に違いはありますか?


私の最初の推測では、SQLエンジンがINを裏でORに変換しない限り、ORの方がパフォーマンスが良いと思います。これら2つのクエリプランを見たことはありますか?
Raj

回答:


170

以下のパフォーマンスの違いを知りたいと思います。

WHERE foo IN ('a', 'b', 'c')
WHERE foo = 'a' OR foo = 'b' OR foo = 'c'

MySQLマニュアルによると、値が定数の場合IN、リストをソートしてからバイナリ検索を使用します。それをOR順不同で一つ一つ評価していくのではないでしょうか。したがってIN、状況によってはより高速です。

知る最良の方法は、特定のデータを使用してデータベースで両方をプロファイルし、どちらが速いかを確認することです。

1000000行のMySQLで両方を試しました。列にインデックスが付けられている場合、パフォーマンスに識別可能な違いはありません。どちらもほぼ瞬時です。列がインデックス付けされていない場合、次の結果が得られました。

SELECT COUNT(*) FROM t_inner WHERE val IN (1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000);
1 row fetched in 0.0032 (1.2679 seconds)

SELECT COUNT(*) FROM t_inner WHERE val = 1000 OR val = 2000 OR val = 3000 OR val = 4000 OR val = 5000 OR val = 6000 OR val = 7000 OR val = 8000 OR val = 9000;
1 row fetched in 0.0026 (1.7385 seconds)

したがって、この場合、ORを使用する方法は約30%遅くなります。さらに用語を追加すると、差が大きくなります。結果は他のデータベースや他のデータによって異なる場合があります。


20
オプティマイザがその価値がある場合は、同じように実行する必要があります。
Janick Bernet、2010年

27
@inflagranti:残念ながら完璧なオプティマイザはありません。オプティマイザは非常に複雑なプログラムであり、各実装には独自の長所と短所があります。これが、特定の実装についてプロファイルする必要があると私が言う理由です。INメソッドの追加構造により、関連する可能性のあるOR節全体よりも最適化が容易になると思います。ORメソッドの方が速いエンジンがあれば驚いていますが、ORが遅い場合があるのも当然です。
マークバイアーズ

2
@MarkByersオプティマイザは常に複数ORのをIN
チムタム

36

見つけるための最良の方法は、実行計画を調べることです。


私はOracleで試してみましたが、まったく同じでした。

CREATE TABLE performance_test AS ( SELECT * FROM dba_objects );

SELECT * FROM performance_test
WHERE object_name IN ('DBMS_STANDARD', 'DBMS_REGISTRY', 'DBMS_LOB' );

クエリでを使用しているIN場合でも、実行プランでは次のように使用すると記載されていますOR

--------------------------------------------------------------------------------------    
| Id  | Operation         | Name             | Rows  | Bytes | Cost (%CPU)| Time     |    
--------------------------------------------------------------------------------------    
|   0 | SELECT STATEMENT  |                  |     8 |  1416 |   163   (2)| 00:00:02 |    
|*  1 |  TABLE ACCESS FULL| PERFORMANCE_TEST |     8 |  1416 |   163   (2)| 00:00:02 |    
--------------------------------------------------------------------------------------    

Predicate Information (identified by operation id):                                       
---------------------------------------------------                                       

   1 - filter("OBJECT_NAME"='DBMS_LOB' OR "OBJECT_NAME"='DBMS_REGISTRY' OR                
              "OBJECT_NAME"='DBMS_STANDARD')                                              

1
テストしている値が3つ以上ある場合、Oracleではどうなりますか?OracleがMySQLと同じバイナリ検索最適化を実行できないのか、それとも両方のケースで実行できるのか知っていますか?
マークバイアーズ

2
@Mark Byers:10個の値を使用して同じクエリを試しましたが、結果は同じです。オプティマイザが私の値をアルファベット順に並べ替えたことに注意してください。Oracleがそのフィルターの内部最適化を行ったとしても、驚くことはありません...
Peter Lang

5
Oracleには、INLIST ITERATOR使用できるインデックスがある場合に選択する操作もあります。それでも、私はそれを試してみた、両方のときINOR同じ実行計画で終わります。
Cheran Shunmugavel

7

OR演算子は、INのように等しいだけでなく、多くの条件を許可するため、IN構成よりもはるかに複雑な評価プロセスを必要とします。

ORで使用できるものと似ていますが、INとは互換性がありません。LIKE以上、またはOracle REGEXP_LIKEに似ているものもあります。さらに、条件が常に同じ値を比較するとは限らないことを考慮してください。

クエリオプティマイザーの場合、同じ値に=演算子を使用して複数の条件でOR演算子を定義する構造体だけなので、IN演算子を管理する方が簡単です。OR演算子を使用する場合、オプティマイザは常に同じ値で=演算子を使用しているとは見なさない場合があり、さらに深くて非常に複雑なエラボレーションを実行しない場合は、 =関係するすべての条件で同じ値の演算子。その結果、前述のバイナリ検索のような最適化された検索方法が除外されます。

[編集]おそらく、オプティマイザは最適化されたIN評価プロセスを実装しない可能性がありますが、これは(データベースバージョンのアップグレードによって)一度発生する可能性があることを除外するものではありません。したがって、OR演算子を使用する場合、その最適化されたエラボレーションは使用されません。


6

私は、オラクルは効率の悪い方(どちらでも)をもう一方に変換するのに十分スマートだと思います。だから私は答えはそれぞれの読みやすさに依存するべきだと思います(私はそれがIN明らかに勝つと思うところ)


2

OR比較する値が少ない場合、(読みやすさの観点から)意味があります。 IN特に有用です。値を比較する動的ソースがある場合。

もう1つの方法はJOIN、一時テーブルでを使用することです。
必要なインデックスがあれば、パフォーマンスに問題はないと思います。


-2

多数のOR(350)でSQLクエリを実行しました。Postgresはそれを437.80ms実行します

ORを使用

ここでINを使用します。

で使用

23.18ms


4
IN句にサブクエリを使用したため、これはまったく同じではありません。
gliljas 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.