【问题标题】:What would cause a query to run slowly when used a subquery, but not when run separately?什么会导致查询在使用子查询时运行缓慢,但在单独运行时不会?
【发布时间】:2009-04-06 21:07:11
【问题描述】:

我有类似以下内容:

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。

【问题讨论】:

  • 您能否指定您正在使用的 MySQL 服务器的确切版本?
  • 谢谢,现在我们正在取得进展。我在我的一个上运行 5.0.24,足够接近。检查一些测试用例,看看那里是否也存在 6.0 alpha 错误。
  • ... 显然不是。奇怪的。您仍然可以根据您的查询检查该错误报告中的示例查询(和解决方法)吗?您的样本看起来与优化器在报告的样本几乎相同。

标签: mysql subquery


【解决方案1】:
【解决方案2】:

如果你这样尝试会发生什么?

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 运算符。

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 是的,我在问题中提到了这一点。看起来一切都很好
    【解决方案4】:

    你不能做另一个联接而不是子查询吗?

    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】:

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

    【讨论】:

    • Ops,我应该给外部和子查询表不同的别名。我的错。
    【解决方案6】:

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

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

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

    时间安排如何?

    【讨论】:

    • 我是故意这样做的,但我确实尝试了不同的名称(我更改了查询),并且花费了相同的时间。
    • 我会说视图选项是个好主意,除了为每 2 个月运行一次的查询创建视图可能不是最好的。 mysql 5 中视图的另一个问题是它们没有索引......所以搜索/加入它们是无用的。
    • 他们确实使用基表中的索引,所以假设这些索引正确,这不是问题。
    • 您认为创建视图、使用它然后立即删除它会更快吗?
    • 离开视图有什么害处?您是按字节租用服务器吗? ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    • 2016-12-12
    • 2011-10-18
    相关资源
    最近更新 更多