在
に対するサブクエリーの最適化は,=
演算子または在(
演算子の場合のようには効果的ではありません。value_list
)在
サブクエリーのパフォーマンスが不十分である一般的な例では,サブクエリーが少数の行を返すのに対し,外部クエリーがサブクエリーの結果と比較して多数の行を返す場合があります。この問題は,
在
サブクエリーを使用するステートメントでは,オプティマイザが相関サブクエリーに書き換えることにあります。非相関サブクエリーを使用する次のステートメントについて説明します。选择……从t1开始。a IN (SELECT b FROM t2);
オプティマイザがステートメントを相関サブクエリーに書き換えます。
选择……从t2中选择1。b = t1.a);
内部クエリーと外部クエリーがそれぞれ
米
行とN
行を返す場合,実行時間は,非相関サブクエリーの場合のo (米
+N
)ではなく,o (米
×N
)になります。つまり,
在
サブクエリーは,このサブクエリーが返す値と同じ値をリストする在(
演算子を使用して作成されたクエリーよりもかなり遅くなる場合があります。value_list
)一般に,テーブルを変更することも,サブクエリーの同じテーブルから選択することもできません。たとえば,この制限は次の形式のステートメントに適用されます。
DELETE FROM t WHERE…(选择…从t…);更新t…WHERE col = (SELECT…从t…);{INSERT|REPLACE} INTO t (SELECT…从t…);
例外:
从
句内の変更されたテーブルでサブクエリーを使用している場合,前述の禁止事項は適用されません。例:更新t…WHERE col = (SELECT * FROM (SELECT…从t…)_t…);
ここでは,
从
句内のサブクエリーの結果が一時テーブルとして格納されるので,t
内の対応する行は,t
に対する更新が行われる前にすでに選択されています。行比較演算は一部のみサポートされています。
の場合,expr
(不)子查询
expr
はn
タプル(行コンストラクタ構文を使用して指定します)にでき,サブクエリーはn
タプルの行を返すことができます。したがって,許可されている構文は,具体的には
と表されますrow_constructor
(不)table_subquery
の場合,expr
人事处
{所有| |一些}子查询
expr
はスカラー値にする必要があり,サブクエリーはカラムサブクエリーにする必要があります。複合カラム行を返すことはできません。
つまり,
n
タプルの行を返すサブクエリーの場合,次のものはサポートされています。(expr_1、……expr_n)[不]table_subquery
ただし,次のものはサポートされていません。
(expr_1、……expr_n)人事处{所有| |一些}子查询
在
の行比較がサポートされているのに,他はサポートされていない理由は,在
が,=
比較および和
演算のシーケンスに,これを書き換えることによって実装されているためです。この方法は,所有
、任何
、一些
には使用できません。从
句のサブクエリーは相関サブクエリーにはできません。これらは,クエリー実行中にすべて実体化(結果セットを生成するように評価)されるので,外部クエリーの行ごとに評価できません。MySQL 5.6.3より前では,実体化は外部クエリーの評価の前に行われます。5.6.3 以降では、オプティマイザは、結果が必要になるまで実体化を遅らせ、これにより実体化を回避できます。セクション8.2.1.18.3 " from句内のサブクエリー(派生テーブル)の最適化"を参照してください。MySQLは特定のサブクエリー演算子にサブクエリーの
限制
をサポートしていません。WHERE s1 IN (SELECT s2 FROM t2 ORDER BY s1 LIMIT 1)错误1235(42000):这个版本的MySQL还不支持'LIMIT & IN/ALL/ANY/SOME子查询'
オプティマイザは,サブクエリーに対してよりも結合に対するほうが完成度が高いので,多くの場合,サブクエリーを使用するステートメントは,結合として書き換えた場合のほうが効率的に実行できます。
在
サブクエリーを选择不同的
結合として書き換えることができる場合には,例外が生じます。例:从t1 WHERE id_col2 IN(从t2 WHERE id_col2 WHERE条件);
このステートメントは次のように書き換えることができます。
从t1中选择不同的col, t2中t1。id_col = t2。id_col和条件;
MySQLでは,サブクエリーで行をテーブルに挿入するなどのデータ変更の副作用があるストアドファンクションを参照できます。たとえば,
f ()
が行を挿入する場合,次のクエリーはデータを変更できます。选择……WHERE x IN (SELECT f()…);
この動作は,sql標準に対する拡張です。米ySQL では、オプティマイザでの処理方法の選択に応じて、特定のクエリーの実行ごとに
f ()
が異なる回数実行される場合があるため,これにより不確定な結果が生成される可能性があります。ステートメントベースまたは混合形式のレプリケーションの場合,この不確定性には,このようなクエリーが,マスターとそのスレーブで異なる結果を生成することがあります。
MySQL 5.6.3より前では,
从
句のサブクエリーは,結果を一時テーブルに実体化することにより評価され,このテーブルではインデックスが使用されません.5.6.3以降では,クエリー実行がさらに高速になる場合は,オプティマイザは実体化されたテーブルにインデックスを作成します。セクション8.2.1.18.3 " from句内のサブクエリー(派生テーブル)の最適化"を参照してください。