大きなデータベースを処理するとき、どちらの方がパフォーマンスが良いですか、IN
それともOR
SQL Where
句ですか?
実行方法に違いはありますか?
大きなデータベースを処理するとき、どちらの方がパフォーマンスが良いですか、IN
それともOR
SQL Where
句ですか?
実行方法に違いはありますか?
回答:
以下のパフォーマンスの違いを知りたいと思います。
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%遅くなります。さらに用語を追加すると、差が大きくなります。結果は他のデータベースや他のデータによって異なる場合があります。
IN
メソッドの追加構造により、関連する可能性のあるOR
節全体よりも最適化が容易になると思います。OR
メソッドの方が速いエンジンがあれば驚いていますが、ORが遅い場合があるのも当然です。
OR
のをIN
?
見つけるための最良の方法は、実行計画を調べることです。
私は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')
INLIST ITERATOR
使用できるインデックスがある場合に選択する操作もあります。それでも、私はそれを試してみた、両方のときIN
とOR
同じ実行計画で終わります。
OR演算子は、INのように等しいだけでなく、多くの条件を許可するため、IN構成よりもはるかに複雑な評価プロセスを必要とします。
ORで使用できるものと似ていますが、INとは互換性がありません。LIKE以上、またはOracle REGEXP_LIKEに似ているものもあります。さらに、条件が常に同じ値を比較するとは限らないことを考慮してください。
クエリオプティマイザーの場合、同じ値に=演算子を使用して複数の条件でOR演算子を定義する構造体だけなので、IN演算子を管理する方が簡単です。OR演算子を使用する場合、オプティマイザは常に同じ値で=演算子を使用しているとは見なさない場合があり、さらに深くて非常に複雑なエラボレーションを実行しない場合は、 =関係するすべての条件で同じ値の演算子。その結果、前述のバイナリ検索のような最適化された検索方法が除外されます。
[編集]おそらく、オプティマイザは最適化されたIN評価プロセスを実装しない可能性がありますが、これは(データベースバージョンのアップグレードによって)一度発生する可能性があることを除外するものではありません。したがって、OR演算子を使用する場合、その最適化されたエラボレーションは使用されません。
多数のOR(350)でSQLクエリを実行しました。Postgresはそれを437.80ms実行します。
ここでINを使用します。
23.18ms