问题描述
我有这样的查询:
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",但我希望先执行此子查询,然后再执行其他条件.
When I use EXPLAIN, there is 'DEPENDENT SUBQUERY' at the end, but I want this subquery to be performed first, before other conditions.
有可能吗?
推荐答案
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]
如果内部表已正确索引,则严格意义上来说,这里的子查询根本不会执行".
If the inner table is properly indexed, the subquery here is not being "performed" at all in a strict sense of word.
由于子查询是IN
表达式的一部分,因此条件被压入子查询中,并转换为EXISTS
.
Since the subquery is a part of an IN
expression, the condition is pushed into the subquery and it's transformed into an EXISTS
.
实际上,此子查询是在每个步骤上评估的:
In fact, this subquery is evaluated on each step:
EXISTS
(
SELECT NULL
FROM [...]
WHERE id = table1.id
)
您实际上可以在EXPLAIN EXTENDED
提供的详细说明中看到它.
You can actually see it in the detailed description provided by EXPLAIN EXTENDED
.
这就是为什么它被称为DEPENDENT SUBQUERY
的原因:每次评估的结果取决于table1.id
的值.这样的子查询是不相关的,它是相关的优化版本.
That's why it's called DEPENDENT SUBQUERY
: the result of each evaluation depends on the value of table1.id
. The subquery as such is not correlated, it's the optimized version that is correlated.
MySQL
总是在更简单的过滤器之后评估EXISTS
子句(因为它们更容易评估,并且有可能根本不会评估子查询).
MySQL
always evaluates the EXISTS
clause after the more simple filters (since they are much easier to evaluate and there is a probability that the subquery won't be evaluated at all).
如果您希望一次评估所有子查询,请按以下方式重写查询:
If you want the subquery to be evaluated all at once, rewrite the query as this:
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
大,则效率更低.
This forces the subquery to be leading in the join, which is more efficient if the subquery is small compared to table_1
, and less efficient if the subquery is large compared to table_1
.
如果子查询中使用的[...].id
上有索引,则将使用INDEX FOR GROUP-BY
执行子查询.
If there is an index on [...].id
used in the subquery, the subquery will be performed using an INDEX FOR GROUP-BY
.
这篇关于我可以强制mysql首先执行子查询吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!