缓慢的SQL查询最大化CPU

问题描述:

我已经继承了一个站点来照顾,并且有一个SQL查询问题,当在站点上运行作业时,这个SQL查询将最大化CPU。缓慢的SQL查询最大化CPU

不幸的是,我是一名前端开发人员,虽然我对简单的sql很好,但这对我来说太复杂了。问题似乎出现在第二个EXISTS及其与主查询的连接中。

以下是代码,它应该收集发送给公司的项目ID列表。

这个查询有什么明显的错误吗?

SELECT mc.id AS company_id, 
     mi.id AS item_id, 
     EXISTS ( 
     SELECT 1 
     FROM mysite AS m2 
     JOIN mysite_order AS mo2 
      ON m2.mysite_order_id = mo2.id 
     WHERE mo2.mysite_item_id = mo.mysite_item_id 
       AND m2.company_email_sent = 'Yes' 
     ) AS email_sent_before, 
     m.id AS mysite_id, 
     m.mysite_code_prefix, 
     m.mysite_code_suffix 
    FROM mysite_company AS mc 
    JOIN mysite_item AS mi 
    ON mc.id = mi.company_id 
    JOIN mysite_order AS mo 
    ON mi.id = mo.mysite_item_id 
    JOIN mysite AS m 
    ON mo.id = m.mysite_order_id 
WHERE mi.avail_end_date <= CURDATE() 
    AND EXISTS ( 
      SELECT 1 
      FROM mysite AS m3 
      JOIN mysite_order AS mo3 
       ON m3.mysite_order_id = mo3.id 
      WHERE mo3.mysite_item_id = mo.mysite_item_id 
       AND m3.company_email_sent = 'No') 
ORDER BY company_id ASC, item_id ASC, m.mysite_code_prefix ASC, 
      m.mysite_code_suffix ASC 
LIMIT 1 
+0

'wo'似乎是一个未定义的别名 - 但这会导致即时错误,而不是CPU挂起 - 可能是您粘贴在那里的错字?除此之外,根据我的经验(当然是Oracle),在查询中出现3次相同大小的表会导致优化器混淆并导致无法预测的性能。 – slothrop 2011-05-27 09:51:45

+0

这是一个错字,应该是'mo'。我会看看第二部分关于正在使用的大表3次,看看我能做些什么来避免这种情况。 – Bunkered 2011-05-27 10:07:07

+0

谢谢...我已经发布了一个稍微更详细的建议作为答案。 – slothrop 2011-05-27 10:29:09

如何使用内联子查询是这样的:

... 
    (SELECT m2.company_email_sent, COUNT(m2.company_email_sent) 
    FROM mysite AS m2 
    JOIN mysite_order AS mo2 
    ON m2.mysite_order_id = mo2.id 
    WHERE mo2.mysite_item_id = mo.mysite_item_id 
    AND m2.company_email_sent IN ('Yes', 'No') 
    GROUP BY m2.company_email_sent) email_status 
... 

然后,您可以加入到该内嵌子查询,并查找是否计数为0,作为替代做这两个独立的EXISTS子查询。

另外 - 我在这里做业务逻辑的假设 - 你不希望在子查询中加入mysite_company吗?即您是否在意有关该项目的电子邮件是否已发送给正在下订单的客户?目前子查询中没有任何内容与外部查询中的mysite_customer相关。

最大的问题是第二个exists()

根据您的要求,它可以替换为mo.company_email_sent = 'No'或加入声明。

更为理想的是,您希望将该exists()语句的值存储在索引字段中。它可以使用触发器或使用应用程序级代码进行设置。