それらは非常によく似た実行プランを生成します(私のテストテーブルでは小さいです。YMMVは常に実際のデータをプロファイルします)。代わりに検討したい3番目の選択肢があります。
最初:
EXPLAIN SELECT * FROM aTable WHERE aField in (SELECT xField FROM bTable WHERE yField > 5);
+ ---- + -------------------- + -------- + ------- + ------ --------- + --------------- + --------- + ------ + ------ + ------------- +
| id | select_type | テーブル| タイプ| possible_keys | キー| key_len | ref | 行| エクストラ|
+ ---- + -------------------- + -------- + ------- + ------ --------- + --------------- + --------- + ------ + ------ + ------------- +
| 1 | プライマリー| aTable | すべて| NULL | NULL | NULL | NULL | 4 | whereを使用する|
| 2 | 依存サブクエリ| bTable | 範囲| bTable_yField | bTable_yField | 5 | NULL | 2 | whereを使用する|
+ ---- + -------------------- + -------- + ------- + ------ --------- + --------------- + --------- + ------ + ------ + ------------- +
二番目:
EXPLAIN SELECT * FROM aTable WHERE (SELECT yField FROM bTable WHERE aTable.aField = bTable.xField) > 5;
+ ---- + -------------------- + -------- + ------ + ------- -------- + ------ + --------- + ------ + ------ + ---------- --- +
| id | select_type | テーブル| タイプ| possible_keys | キー| key_len | ref | 行| エクストラ|
+ ---- + -------------------- + -------- + ------ + ------- -------- + ------ + --------- + ------ + ------ + ---------- --- +
| 1 | プライマリー| aTable | すべて| NULL | NULL | NULL | NULL | 4 | whereを使用する|
| 2 | 依存サブクエリ| bTable | すべて| NULL | NULL | NULL | NULL | 4 | whereを使用する|
+ ---- + -------------------- + -------- + ------ + ------- -------- + ------ + --------- + ------ + ------ + ---------- --- +
どちらも依存サブクエリになります。私のサンプルテーブルでは、最初のテーブルはインデックスの恩恵を受けていますが(私bTable.yField
はインデックスが付けられていると思います)、2番目のテーブルはそうではありません。
JOIN
依存サブクエリを回避し、 :を使用して事前フィルタリングを改善できます。
3番目の選択肢:
EXPLAIN SELECT * FROM aTable INNER JOIN bTable On aTable.aField = bTable.xField WHERE bTable.yField > 5;
+ ---- + ------------- + -------- + ------- + ------------- -+ --------------- + --------- + ------ + ------ + ------- ------------------------- +
| id | select_type | テーブル| タイプ| possible_keys | キー| key_len | ref | 行| エクストラ|
+ ---- + ------------- + -------- + ------- + ------------- -+ --------------- + --------- + ------ + ------ + ------- ------------------------- +
| 1 | シンプル| bTable | 範囲| bTable_yField | bTable_yField | 5 | NULL | 2 | whereを使用する|
| 1 | シンプル| aTable | すべて| NULL | NULL | NULL | NULL | 4 | whereを使用する; 結合バッファの使用|
+ ---- + ------------- + -------- + ------- + ------------- -+ --------------- + --------- + ------ + ------ + ------- ------------------------- +
ただし、オプティマイザがさまざまな決定を行う可能性があるため、スキーマと代表的な実世界のデータを使用してプロファイリングする必要があります。
quassnoiによるこの優れた記事で、これらの種類の手法をさらに比較します。
参考までに、クエリを作成aTable
し、bTable
(定義を提供しなかったため)テストした方法は次のとおりです。
mysql> CREATE TABLE aTable(aField INT、aMore VARCHAR(200));
クエリOK、影響を受けた0行(0.01秒)
mysql> CREATE TABLE bTable(xField INT、yField INT);
クエリOK、影響を受ける行は0(0.02秒)
mysql> INSERT INTO aTable(aField、aMore)VALUES(1、'One')、(2、'Two')、(3、'Three')、(4、'Four');
クエリOK、影響を受ける4行(0.00秒)
レコード:4重複:0警告:0
mysql> INSERT INTO bTable(xField、yField)VALUES(1、10)、(2、2)、(3、20)、(4、4);
クエリOK、影響を受ける4行(0.02秒)
レコード:4重複:0警告:0
mysql> CREATE INDEX bTable_yField ON bTable(yField);
クエリOK、影響を受けた0行(0.05秒)
レコード:0重複:0警告:0
mysql> SELECT * FROM aTable WHERE aField in(SELECT xField FROM bTable WHERE yField> 5);
+ -------- + ------- +
| aField | aMore |
+ -------- + ------- +
| 1 | 1つ|
| 3 | 3つ|
+ -------- + ------- +
セットの2行(0.00秒)
mysql> SELECT * FROM aTable WHERE(SELECT yField FROM bTable WHERE aTable.aField = bTable.xField)> 5;
+ -------- + ------- +
| aField | aMore |
+ -------- + ------- +
| 1 | 1つ|
| 3 | 3つ|
+ -------- + ------- +
セットの2行(0.00秒)