我有以下查询:
select
qs.*
from
(
select
tsk.id,
tsk.request_id,
tsk.hash_id
from
user_tasks as usr
inner join unassigned_tasks as tsk on usr.task_id = tsk.id
where
usr.assigned_to = 53
AND tsk.product_id NOT IN (
SELECT
product_id
FROM
product_progresses
WHERE
request_id = tsk.request_id
)
ORDER BY
tsk.id
) as qs <-- this takes about 233ms.
WHERE
qs.id = ( <-- should this subquery execute for every row from outer result-set row?
SELECT
min(qt.id)
FROM
(
select
tsk.id,
tsk.request_id,
tsk.hash_id
from
user_tasks as usr
inner join unassigned_tasks as tsk on usr.task_id = tsk.id
where
usr.assigned_to = 53
AND tsk.product_id NOT IN (
SELECT
product_id
FROM
product_progresses
WHERE
request_id = tsk.request_id
)
ORDER BY
tsk.id
) as qt <-- this takes about 233ms.
WHERE
qt.id > 83934
)
qs
和qt
的执行时间大约相同,即大约233ms
。
此外,执行整个查询大约需要相同的时间。
我有一个概念,where qs.id = (...)
内的内部查询对qs
生成的结果集中的每一行执行一次。
在当前情况下,qs
输出10
行。
所以我决定测试是否对每行执行10次子查询。
这是我放入子查询中的内容:
WHERE qs.id = (
SELECT
SLEEP(1)
)
代替where qs.id = ( select min(qt.id) ... )
。
这花费了10.246
,这证明内部查询正在针对每一行运行。
因此,初始查询不应该花费(qt time) 233 * 10 (rows from qs)
= 2330
毫秒吗?
是因为select min()..
仅计算一次?
答案 0 :(得分:0)
在MySQL中,FROM
子句中的子查询先于WHERE
子句中的子查询求值。
有用的文章: https://www.eversql.com/sql-order-of-operations-sql-query-order-of-execution/
在您的情况下,这导致qs
在加入WHERE
子句之前得到充分评估。如果希望qs
受qt
限制,则应可以通过取消嵌套qs
或在qt
中移动qs
来实现这一目标。
尽管实际上,与其对WHERE
子句使用子查询,不如使用联接。