我有这样的查询:
SELECT `table_1`.* from `table_1`
INNER JOIN `table_2` [...]
INNER JOIN `table_3` [...]
WHERE `table_1`.`id` IN(
SELECT `id` FROM [...]
)
AND [more conditions]当我使用EXPLAIN时,末尾有'DEPENDENT SUBQUERY‘,但我希望在其他条件之前先执行此子查询。
这是可能的吗?
发布于 2009-11-20 06:08:17
SELECT `table_1`.*
FROM `table_1`
INNER JOIN
`table_2` [...]
INNER JOIN
`table_3` [...]
WHERE `table_1`.`id` IN
(
SELECT `id`
FROM [...]
)
AND [more conditions]如果内部表被正确索引,这里的子查询在严格的word意义上根本就不是“执行”的。
由于子查询是IN表达式的一部分,因此将条件推入子查询并将其转换为EXISTS。
实际上,此子查询在每个步骤中都会被计算:
EXISTS
(
SELECT NULL
FROM [...]
WHERE id = table1.id
)你可以在EXPLAIN EXTENDED提供的详细描述中看到它。
这就是为什么它被称为DEPENDENT SUBQUERY:每次求值的结果取决于table1.id的值。子查询本身是不相关的,它是相关的优化版本。
MySQL总是在更简单的过滤器之后对EXISTS子句求值(因为它们更容易求值,而且子查询有可能根本不被求值)。
如果希望一次性计算子查询,请将查询重写为:
SELECT table_1.*
FROM (
SELECT DISTINCT id
FROM [...]
) q
JOIN table_1
ON table_1.id = q.id
JOIN table_2
ON [...]
JOIN table_3
ON [...]
WHERE [more conditions]这将强制子查询在连接中领先,如果子查询与table_1相比较小,则效率较高;如果与table_1相比,子查询较大,则效率较低。
如果子查询中使用了[...].id上的索引,则将使用INDEX FOR GROUP-BY执行子查询。
发布于 2009-11-20 06:08:34
这是mysql中的一个已知错误:http://bugs.mysql.com/bug.php?id=25926
一种有用的解决方法是将子查询下推到另一个select * from (subquery) as dt类型子查询中。
发布于 2009-11-20 05:30:17
您可以先将子查询的结果选择到一个临时表中,然后在主查询中连接到它。
https://stackoverflow.com/questions/1766702
复制相似问题