開発が進行中なので、最適化についての情報は長期的に信頼性があります。次のリストは、利用してみたいいくつかの興味深いトリックを紹介しています。
サブクエリー内の行数や行の順番に影響を与えるサブクエリー節を利用してください。例 :
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 の互換性で、いくつかのサブクエリーは結合に変形することができます。しかし、いくつかの場合で、サブクエリーを結合に変換することで性能を向上させることができます。項8.2.9.11. 「結合としてのサブクエリーの書き換え」 を参照してください。
節をサブクエリーの外から中に移動させてください。たとえば、次の例を
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
機能を利用すると、今の状況を改善するためのアイデアを見付けることができます。項7.11.3. 「情報関数」
を参照してください。
MySQL 自体が行う最適化のいくつかは次のようなものです。
MySQL は、非相関サブクエリーを 1
回のみ実行します。指定されたサブクエリーが実際に非相関であることを確認するには、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} {> | < | >= | <=} (uncorrelated subquery
)
たとえば、次の
WHERE
節ですが、
WHERE 5 > ALL (SELECT x FROM t)
オプティマイザによってこのように扱われるでしょう。
WHERE 5 > (SELECT MAX(x) FROM t)
『MySQL Internals Manual』の章「How MySQL Transforms Subqueries」も参照してください。