我有类似以下的内容:
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。
答案 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
,因此必须为外部表中的每一行运行一次 - 内部查询的结果将随外部表中的每一行而变化