在使用子查询时,什么会导致查询运行缓慢,但在单独运行时不会?

时间:2009-04-06 21:07:11

标签: mysql subquery

我有类似以下的内容:

SELECT c.id
FROM contact AS c
WHERE c.id IN (SELECT s.contact_id 
    FROM sub_table AS s
        LEFT JOIN contact_sub AS c2 ON (s.id = c2.sub_field)
    WHERE c2.phone LIKE '535%')
ORDER BY c.name

问题是查询需要非常长的时间(> 2分钟),但是如果我使用子查询,单独运行它,内嵌id并将它们插入到主查询中,它运行的时间远小于1秒,包括数据回溯和内爆。

我已经检查了两种方法的解释,并且正确使用了相同的方法。子查询不会返回超过200个ID。

什么可能导致子查询方法花费更长时间?

顺便说一句,我知道上面的查询可以用连接编写,但我的查询不能 - 这只是一个简化版本。

使用MySQL 5.0.22。

6 个答案:

答案 0 :(得分:3)

答案 1 :(得分:1)

如果你这样尝试会怎么样?

SELECT c.id
FROM contact AS c
INNER JOIN (SELECT s.contact_id 
    FROM sub_table AS s
        LEFT JOIN contact_sub AS c2 ON (s.id = c2.sub_field)
    WHERE c2.phone LIKE '535%') subq ON subq.contact_id=c.id
ORDER BY c.name

假设s.contact_id的结果是唯一的。如果不是,则可以向子查询添加distinct。

我总是以这种方式使用不相关的子查询,而不是在where子句中使用IN运算符。

答案 2 :(得分:0)

您是否检查了查询的执行计划?这通常会告诉你问题。

答案 3 :(得分:0)

这是相关的子查询。它在外部选择中为每行运行一次。 (我认为。你有两个具有相同相关名称的表,我假设这是一个错字。你说它不能被重写为连接意味着它是相关的。)

好的,我会给你一些尝试。你说子查询没有相关性,你仍然无法加入它。而且你获取子查询的输出,并用词法替换子查询的输出,主查询运行得更快。

所以试试这个:将子查询放到视图中:create view foo后跟子查询的文本。然后重写主查询以除去“IN”子句,而是加入视图。

时间如何?

答案 4 :(得分:0)

你不能再做一次连接而不是子查询吗?

SELECT c.id
FROM contact AS c
JOIN sub_table AS s on c.id = s.contact_id
LEFT JOIN contact_sub AS cs ON (s.id = cs.sub_field)
WHERE cs.phone LIKE '535%'
ORDER BY c.name

答案 5 :(得分:0)

由于子查询引用外部select中的字段sub_field,因此必须为外部表中的每一行运行一次 - 内部查询的结果将随外部表中的每一行而变化