2011-05-27 70 views
1

我已經繼承了一個站點來照顧,並且有一個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

回答

0

如何使用內聯子查詢是這樣的:

... 
    (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相關。

0

最大的問題是第二個exists()

根據您的要求,它可以替換爲mo.company_email_sent = 'No'或加入聲明。

更爲理想的是,您希望將該exists()語句的值存儲在索引字段中。它可以使用觸發器或使用應用程序級代碼進行設置。