開発が進行中なので、最適化についての情報は長期的に信頼性があります。次のリストは、利用してみたいいくつかの興味深いトリックを紹介しています。
サブクエリ内の行数や行の順番に影響を与えるサブクエリ条項を利用してください。例:
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;
サブクエリをサポートしない古いバージョンの MySQL の互換性で、いくつかのサブクエリは接合に変形する事ができます。しかし、いくつかの場合で、サブクエリを接合に変換する事で性能を向上させる事ができます。詳しくは 項12.2.8.11. 「MySQL 初期バージョンにおいて、サブクエリの接合としての書き換え」 を参照してください。
条項をサブクエリの外から中に移動させて下さい。例えば、次の例を
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);
別の例として、このクエリを、
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
を利用してください。
必ず1つの行を返す相関サブクエリに対しては、IN
は必ず =
よりも遅いです。例えば、次の例を
SELECT * FROM t1 WHERE t1.col_name
= (SELECT a FROM t2 WHERE b =some_const
);
この次のクエリの代わりに利用します。
SELECT * FROM t1 WHERE t1.col_name
IN (SELECT a FROM t2 WHERE b =some_const
);
これらのトリックは、プログラムを早くしたり、遅くしたりする可能性があります。BENCHMARK()
関数のような MySQL
機能を利用すると、今の状況を改善する為のアイデアを見付ける事ができます。詳しくは
項11.10.3. 「情報関数」
を参照してください。
MySQL 自体が行う最適化のいくつかは次のような物です。
MySQL
は非相関サブクエリを一度だけ実行します。EXPLAIN
を利用して、与えられたサブクエリが本当に非相関であるかどうかを確認してください。
MySQL は、サブクエリ中の選択リスト
カラムがインデックスされる可能性の利点を利用する為に
IN
、ALL
、ANY
、そして
SOME
サブクエリを書き換えます。
MySQL は、EXPLAIN
が特別な接合タイプ(unique_subquery
または
index_subquery
)として表現する、インデックス検索機能を利用した次の形のサブクエリを置き換えます。
... IN (SELECTindexed_column
FROMsingle_table
...)
MySQL は、NULL
値か空のセットが関連していない限り、MIN()
または MAX()
を含む式を利用した次の形の式を強化します。
value
{ALL|ANY|SOME} {> | < | >= | <=} (non-correlated subquery
)
例えば、次の WHERE
条項ですが、
WHERE 5 > ALL (SELECT x FROM t)
オプチマイザによってこのように扱われるでしょう。
WHERE 5 > (SELECT MAX(x) FROM t)
「MySQL がどのようにサブクエリを変形させるか」 というタイトルの章が、MySQL 内部マニュアルの http://dev.mysql.com/doc/ で参照可能です。