0

我有类似以下内容:

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 秒,包括数据检索和内爆。

我已经检查了有关方法和密钥的说明是否正确使用并且方式相同。子查询返回的 ID 不超过 200 个。

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

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

使用 MySQL 5.0.22。

4

6 回答 6

3

听起来很像MySQL bug #32665: Query withdependent subquery is too slow

于 2009-04-06T21:12:57.247 回答
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 运算符。

于 2009-04-06T21:36:38.093 回答
0

您是否检查过查询的执行计划?这通常会向您显示问题。

于 2009-04-06T21:11:28.980 回答
0

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

好的,我会给你一些东西来试试。您说子查询不相关,并且您仍然无法加入它。如果您获取子查询的输出,并在词法上将其替换为子查询,则主查询的运行速度要快得多。

所以试试这个:将子查询变成一个视图:create view foo后跟子查询的文本。然后重写主查询以摆脱“IN”子句,而是加入视图。

那个时间点怎么样?

于 2009-04-06T21:13:01.800 回答
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
于 2009-04-06T21:16:08.080 回答
0

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

于 2009-04-06T21:16:16.987 回答