当 = (子查询) 速度很快时,为什么 IN (子查询) 表现不佳?

Mat*_*nco 5 mysql innodb subquery

看看这两个查询:

简单的:

mysql> SELECT * FROM omgbatch JOIN omgoutput ON (idomgbatch=omgbatch) WHERE idomgoutput = (SELECT DISTINCT lastoutput FROM omgenvelope WHERE lastinput=18658);
+------------+-------+------------+------- ------+---------+----------+
| idomgbatch | 芦丁 | 批处理时间 | idmgoutput | 流量模式 | omgbatch |
+------------+-------+------------+------- ------+---------+----------+
| 12174 | 8 | 20140508040930-832 | 10728 | 162 | 12174 |
+------------+-------+------------+------- ------+---------+----------+
1 行(0.00 秒)

复杂的:

mysql> SELECT * FROM omgbatch JOIN omgoutput ON (idomgbatch=omgbatch) WHERE idomgoutput IN (SELECT DISTINCT lastoutput FROM omgenvelope WHERE lastinput=18658);
+------------+-------+------------+------- ------+---------+----------+
| idomgbatch | 芦丁 | 批处理时间 | idmgoutput | 流量模式 | omgbatch |
+------------+-------+------------+------- ------+---------+----------+
| 12174 | 8 | 20140508040930-832 | 10728 | 162 | 12174 |
+------------+-------+------------+------- ------+---------+----------+
1 排(7.40 秒)

在这种情况下,我知道子查询仅返回 1 个值 ( 12174),因此我可以将=运算符用于子查询结果集并在 0.00 秒内得到答案。

当我保留IN操作员时,整整需要 7.4 秒。我已将代码更改为子查询的循环和=“主”选择中的简单代码,一切都很好,但我仍然想了解这背后的机制。

我太菜了,无法理解EXPLAIN命令中的所有细节。

与查询IN列表三行SELECT_TYPE PRIMARYPRIMARY以及DEPENDENT SUBQUERY与相应的行数101721721。对应的“键”:NULL, PRIMARY, fk_omgenvelope_omginput1_idx

=一个只能匹配值1版本而不是做select_types PRIMARYPRIMARYSUBQUERY与行数11以及721

10114行表omgoutput1854182行表omgenvelope10108行的表omgbatch,所以我不明白是什么10172在复杂的EXPLAIN输出来的。

为了完整起见,以下是查询计划的完整解释:

简单的:

+----+-------------+------------+---------+-------- -----------------------------+------------ ---------+---------+-------+------+-------------- ---------------+
| 身份证 | 选择类型 | 表| 类型 | 可能的密钥| 关键| 密钥长度 | 参考 | 行 | 额外 |
+----+-------------+------------+---------+-------- -----------------------------+------------ ---------+---------+-------+------+-------------- ---------------+
| 1 | 主要 | 输出| 常量 | PRIMARY,fk_omgoutput_omgbatch1_idx | 主要 | 4 | 常量 | 1 | |
| 1 | 主要 | omgbatch | 常量 | 主要 | 主要 | 4 | 常量 | 1 | |
| 2 | 子查询 | omgenvelope | 参考 | fk_omgenvelope_omginput1_idx | fk_omgenvelope_omginput1_idx | 4 | | 第721话 使用哪里;使用临时|
+----+-------------+------------+---------+-------- -----------------------------+------------ ---------+---------+-------+------+-------------- ---------------+

复杂的:

+----+------------+------------+--------+ -------------------------------------------------- ----------+------------------------------+-------- -+-----------------------------+-------+--------- ---------------------+
| 身份证 | 选择类型 | 表| 类型 | 可能的密钥| 关键| 密钥长度 | 参考 | 行 | 额外 |
+----+------------+------------+--------+ -------------------------------------------------- ----------+------------------------------+-------- -+-----------------------------+-------+--------- ---------------------+
| 1 | 主要 | 输出| 所有 | fk_omgoutput_omgbatch1_idx | 空 | 空 | 空 | 10173 | 使用 where |
| 1 | 主要 | omgbatch | eq_ref | 主要 | 主要 | 4 | trackdb.omgoutput.omgbatch | 1 | |
| 2 | 相关子查询 | omgenvelope | 参考 | fk_omgenvelope_omginput1_idx,fk_omgenvelope_omgoutput1_idx | fk_omgenvelope_omginput1_idx | 4 | 常量 | 第721话 使用哪里;使用临时|
+----+------------+------------+--------+ -------------------------------------------------- ----------+------------------------------+-------- -+-----------------------------+-------+--------- ---------------------+

解析这个时我会怎么想?DEPENDENT SUBQUERY和 just SUBQUERYwithoutdependent和有什么不一样?

它似乎不仅仅是IN执行它的子查询中的 1 个以上潜在行。用几个常量值替换子查询也很快:

mysql> 解释 SELECT * FROM omgbatch JOIN omgoutput ON (idomgbatch=omgbatch) WHERE idomgoutput IN (10728,10729,10000,10,100,0,23123);
+----+-------------+-----------+--------+--------- ---------------------------+---------+---------+-- ---------------------------+------+------------+
| 身份证 | 选择类型 | 表| 类型 | 可能的密钥| 关键| 密钥长度 | 参考 | 行 | 额外 |
+----+-------------+-----------+--------+--------- ---------------------------+---------+---------+-- ---------------------------+------+------------+
| 1 | 简单 | 输出| 范围| PRIMARY,fk_omgoutput_omgbatch1_idx | 主要 | 4 | 空 | 7 | 使用 where |
| 1 | 简单 | omgbatch | eq_ref | 主要 | 主要 | 4 | trackdb.omgoutput.omgbatch | 1 | |
+----+-------------+-----------+--------+--------- ---------------------------+---------+---------+-- ---------------------------+------+------------+

Mat*_*nco 3

根据这个答案

这是 MySQL 中的一个已知问题。有传言说它将被修复。

该问题是由于当使用 IN 的子查询被错误地识别为从属子查询而不是独立子查询时缺少优化所致。

这会导致子查询运行大量次,这是不必要的。