現在、MySQL 5.6.10 を使用しています。
私の実際のクエリはもっと複雑ですが、問題を再現する簡単な方法を次に示します。以下のクエリが役に立たないことはわかっています (select id from x where id in (select id from x...)) が、私の主張を証明しています。
このテーブルを作成しました:
CREATE TABLE test (
id INT NOT NULL AUTO_INCREMENT ,
PRIMARY KEY (id));
次に、このコマンドを 5 回実行しました。テーブルに 50 行が作成されました。
INSERT INTO test (id) VALUES(null),(null),(null),(null),(null),(null),(null),(null),(null),(null);
そして、この説明を実行しました:
EXPLAIN SELECT id FROM test WHERE
id in (SELECT id FROM test WHERE id < 5);
そして、これを得ました:
これは私にとって完全に理にかなっています。しかし、次のように、別の IN を使用して WHERE 句に OR を追加すると、次のようになります。
EXPLAIN SELECT id FROM test WHERE
id IN (SELECT id FROM test WHERE id < 5)
OR id IN (SELECT id FROM test WHERE id > 45);
突然、MySQL は 50 行すべてを見ています。
SELECT id FROM test WHERE id < 5 OR id > 45
クエリが、または UNION などとして書き直される可能性があることはわかっていますが、それは重要ではありません。問題は、MySQL が調べている行が多すぎるということです。
最初のクエリで FLUSH STATUS / SHOW STATUS LIKE "Handler%" を実行すると、次のようになります。
Handler_read_key 5
Handler_external_lock 4
Handler_read_next 4
Handler_read_first 1
しかし、2 番目のクエリに対してこれを行うと、次のようになります。
Handler_read_key 99
Handler_write 9
Handler_external_lock 6
Handler_read_next 59
Handler_read_first 2
大きな違いはなぜですか?それがオプティマイザーなのだろうか、もしそうなら、この「最適化」を防ぐクエリに含めることができるオプションはありますか? これは、私が開発しているクエリにとって実際的な意味を持ちます。数百行だけを調べる代わりに、MySQL は 120,000 行を調べています。