開発は現在進行形で進められているため、長期間有効な最適化のヒントというのはありません。ここでは、いくつかのテクニックについて説明します。
サブクエリのレコード数やレコードの順序に影響するサブクエリ節を使用する。次はその例。
SELECT * FROM t1 WHERE t1.column1 IN (SELECT column1 FROM t2 ORDER BY column1); SELECT * FROM t1 WHERE t1.column1 IN (SELECT DISTINCT column1 FROM t2); SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 LIMIT 1);
結合をサブクエリに置き換える。次はその例。
SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN ( SELECT column1 FROM t2);
上のステートメントは次のステートメントの代わりに使用できる。
SELECT DISTINCT t1.column1 FROM t1, t2 WHERE t1.column1 = t2.column1;
サブクエリの外側から内側へ節を移動する。次はその例。
SELECT * FROM t1 WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);
上のステートメントは次のステートメントの代わりに使用できる。
SELECT * FROM t1 WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);
もう 1 つの例。
SELECT (SELECT column1 + 5 FROM t1) FROM t2;
上のステートメントは次のステートメントの代わりに使用できる。
SELECT (SELECT column1 FROM t1) + 5 FROM t2;
相関副問い合わせの代わりに行副問い合わせを使用する。次はその例。
SELECT * FROM t1 WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);
上のステートメントは次のステートメントの代わりに使用できる。
SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1 AND t2.column2=t1.column2);
a <> ALL (...)
ではなく、NOT (a = ANY (...))
を使用する。
x=1 OR x=2
ではなく x =
ANY (table containing {1,2})
を使用する。
EXISTS
ではなく =
ANY
を使用する。
上記のテクニックを使用すると、プログラムの実行が速くなったり、遅くなったりする場合があります。MySQL
の BENCHMARK()
関数などの機能を使用すると、それぞれの状況において何が適切か、調べることができます。旧バージョンとの互換性を確保する場合を除いて、結合への変換についてはあまり気にしないでください。
MySQL 自体が行う最適化として次のものがあります。
非相関副問い合わせは 1
度しか実行されない(EXPLAIN
を使用して、指定されたサブクエリが実際に非相関副問い合わせかどうか確認できる)
IN
/ALL
/ANY
/SOME
サブクエリは、サブクエリ内の選択リストカラムがインデックス付きである可能性があるため、書き直される。
次の形式のサブクエリはインデックスルックアップ関数と置き換えられる。
... IN (SELECT indexed_column FROM single_table ...)
インデックスルックアップ関数は、EXPLAIN
では特殊な結合型として記述される。
次の形式の式は、MIN
または
MAX
を含む式で拡張される(NULL
値や空のセットが含まれている場合を除く)。
value {ALL|ANY|SOME} {> | < | >= | <=} (non-correlated subquery)
例
WHERE 5 > ALL (SELECT x FROM t)
上の式は次のように処理される。
WHERE 5 > (SELECT MAX(x) FROM t)
MySQL Internals Manual(MySQL
内部情報マニュアル)に ``How MySQL Transforms
Subqueries(MySQL によるサブクエリの変換)''
という章があります。このマニュアルを参照するには、MySQL
のソースパッケージをダウンロードして、internals.texi
というファイルを探してください。
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.