我目前正在使用 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
但是,如果我对第二个查询这样做,我会得到:
Handler_read_key 99
Handler_write 9
Handler_external_lock 6
Handler_read_next 59
Handler_read_first 2
为什么差别很大?我想知道它是否是优化器,如果是,是否可以在查询中包含一些选项来阻止这种“优化”?这对我正在开发的查询具有真正的实际意义。MySQL 不是只检查几百行,而是检查 120,000 行。