等号とIN演算子の値が同じ場合、SQLエンジンはどのように異なりますか?実行時間は変わりますか?
等価チェック演算子を使用する最初の1つ
WHERE column_value = 'All'
2つ目はOR演算子と単一値を使用
WHERE column_value IN ('All')
値が1つしかない場合、SQLエンジンはIN
を=
に変更しますか?
MySQLとPostgreSQLで同じものに違いはありますか?
これら2つのステートメントに違いはありません。オプティマイザーは、IN
に要素が1つしかない場合、IN
を_=
_に変換します。
ただし、このような質問がある場合は、両方のステートメントを実行し、実行プランを実行して違いを確認してください。ここでは、何も見つかりません。
オンラインで大規模な検索を行った後、これをサポートするSQLのドキュメントを見つけました(すべてのDBMSに適用されると思います)。
括弧内に値が1つしかない場合、このコマンドは次と同等です。
WHERE "column_name" = 'value1
Oracleの両方のクエリの実行計画を次に示します(ほとんどのDBMSはこれを同じように処理します)。
_EXPLAIN PLAN FOR
select * from dim_employees t
where t.identity_number = '123456789'
Plan hash value: 2312174735
-----------------------------------------------------
| Id | Operation | Name |
-----------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| DIM_EMPLOYEES |
| 2 | INDEX UNIQUE SCAN | SYS_C0029838 |
-----------------------------------------------------
_
IN()
の場合:
_EXPLAIN PLAN FOR
select * from dim_employees t
where t.identity_number in('123456789');
Plan hash value: 2312174735
-----------------------------------------------------
| Id | Operation | Name |
-----------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| DIM_EMPLOYEES |
| 2 | INDEX UNIQUE SCAN | SYS_C0029838 |
-----------------------------------------------------
_
ご覧のとおり、どちらも同じです。これは、インデックス列にあります。インデックスなしの列(テーブル全体のスキャンのみ)についても同様です。
単一の値で使用する場合、違いはありません。上記の2つのクエリのテーブルスキャン、インデックススキャン、またはインデックスシークをチェックすると、2つのクエリに違いがないことがわかります。
MysqlとPostgresSQLに同じような違いはありますか?
いいえ、2つのエンジンに違いはありません(実際には、SQL Server、Oracleなどを含むほとんどのデータベースで同じです)。両方のエンジンがIN
を=
に変換します
それほど大きな違いはありませんが、column_valueにインデックスが付けられている場合、IN
演算子はインデックスとして読み取れない場合があります。
この問題に一度遭遇したので、注意してください。
男に魚などを教えます。ここでは、クエリのバリエーションが何をするかを自分で確認する方法を示します。
mysql> EXPLAIN SELECT * FROM sentence WHERE sentence_lang_id = "AMH"\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: sentence
type: ref
possible_keys: sentence_lang_id
key: sentence_lang_id
key_len: 153
ref: const
rows: 442
Extra: Using where
そして、他の方法で試してみましょう:
mysql> EXPLAIN SELECT * FROM sentence WHERE sentence_lang_id in ("AMH")\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: sentence
type: ref
possible_keys: sentence_lang_id
key: sentence_lang_id
key_len: 153
ref: const
rows: 442
Extra: Using where
Mysql EXPLAIN
リクエストの結果を解釈する方法について here を読むことができます。現時点では、両方のクエリで同一の出力が得られていることに注意してください。まったく同じ「実行計画」が生成されます。 type
行は、クエリが一意でないインデックス(この場合は外部キー)を使用することを示し、ref
行は、クエリが定数値を比較することによって実行されることを示しますこのインデックスに対して。
単一のIN句の場合、違いはありません。以下は、EMPSテーブルを使用したデモです。
select * from emps where empid in (1)
select * from emps where empid=1
実行計画の最初のクエリの述語:
[PerformanceV3].[dbo].[Emps].[empID]=CONVERT_IMPLICIT(int,[@1],0)
実行計画の2番目のクエリの述語:
[PerformanceV3].[dbo].[Emps].[empID]=CONVERT_IMPLICIT(int,[@1],0)
IN句に複数の値がある場合、それらを結合に変換する方が良い
別の観点を追加するために、rdbmsシステムの主なポイントの1つは、クエリを書き換えて、そのクエリとすべての同等のクエリに最適な実行プランを選択することです。これは、2つのクエリが論理的に同一である限り、特定のrdbmsで常に同じ実行プランを生成する必要があることを意味します。
そうは言っても、多くのクエリは同等です(同じ結果セット)が、データベース自体が認識していない制約があるため、これらのケースに注意してください(たとえば、1から6の数値フィールドの場合、dbは<3
を知りません) in (1,2)
)と同じです。しかし、結局のところ、and
およびor
ステートメントの読みやすさを考えているだけであれば、どのように記述してもパフォーマンスに影響はありません。
両方で実行計画を実行し、結果を確認する必要があります。
IN()
ステートメント内に値が1つだけ配置されている場合、通常の=
記号と同じように実行されるため、実行計画は同じだと思います。
このようなクエリでオプティマイザが異なる動作をする理由はありません。