2014-10-28 122 views
0

說明: Complaint_status包含特定的投訴多行,試圖讓用戶明智的封閉投訴(狀態= 2和值IN(1,2))建議優化MySQL查詢

痛點:

YEAR(cs.created_at)=year(curdate()) 
AND MONTH(cs.created_at)=month(curdate()) 

以本地幾乎5分鐘,並在服務器

SELECT u3.name,COUNT(c3.id) as closed_tickets 
FROM complaint c3,complaint_status cs,assignment a3,user u3 
WHERE 
c3.id=cs.complaint_id 
AND a3.complaint_id=c3.id 
AND u3.id=a3.assigned_to 
AND u3.user_type=14 
AND a3.expiry IS NULL 
AND cs.id IN(SELECT MAX(id) FROM complaint_status WHERE complaint_id=c3.id AND status=2 AND value IN(1,2)) 
AND YEAR(cs.created_at)=year(curdate()) 
AND MONTH(cs.created_at)=month(curdate()) 
GROUP BY u3.id 
ORDER BY COUNT(c3.id) DESC 
+0

將這個查詢之前的解釋,並與結果編輯你的問題。 – Mihai 2014-10-28 09:26:50

+0

你不明白看這裏http://www.sitepoint.com/using-explain-to-write-better-mysql-queries/ – Mihai 2014-10-28 09:31:47

回答

1

WHERE子句中應用此謂詞問題1.5分鐘:

YEAR(cs.created_at)=year(curdate()) 
AND MONTH(cs.created_at)=month(curdate()) 

是MySql需要評估所有記錄(或至少剩下的那些)的這些函數。這裏的浪費是這些實際上是常數,取決於當前的日期。假設有created_at索引,則可以通過將日期與本月的第一天進行比較,並且小於下個月的第一天(並假設created_at是DATE),來改善hitting the index的機會:

...

cs.created_at >= DATE_SUB(CURRENT_DATE, INTERVAL DAYOFMONTH(CURRENT_DATE)-1 DAY), 
    AND cs.created_at < DATE_ADD(LAST_DAY(CURRENT_DATE), INTERVAL + 1 DAY) 

注意,結束日期不包括上限(因爲這可能包括對下一個月的第一第二數據)

1

首先,你要修復join狀態。

二,而不是:

YEAR(cs.created_at) = year(curdate()) AND MONTH(cs.created_at) = month(curdate()) 

用途:

cs.created_at >= curdate() and cs_created_at < date_sub(date_sub, curdate(), interval day(curdate()) - 1, interval 1 month) 

這將使該領域使用具有created_at任何索引。

這似乎是你的具體問題。

如果你真的想優化查詢,我建議請另一問題有:

  • 有明確改寫查詢聯接
  • 表佈局(或至少現有的索引)
  • 查詢的解釋計劃。
+0

你可能會錯過一些括號。 – Mihai 2014-10-28 09:56:56

1

嘗試:

SELECT u3.name, 
     COUNT(c3.id) AS closed_tickets 
FROM complaint c3 
JOIN complaint_status cs 
    ON c3.id=cs.complaint_id 
JOIN ASSIGNMENT a3 
    ON a3.complaint_id=c3.id 
JOIN USER u3 
    ON u3.id=a3.assigned_to 
JOIN (SELECT complaint_id, 
       MAX(id) id 
      FROM complaint_status 
      WHERE status=2 
      AND value IN(1,2) 
      GROUP BY complaint_id) cs9 
    ON cs9.complaint_id=c3.id 
    AND cs.id = cs9.id 
WHERE u3.user_type=14 
    AND a3.expiry IS NULL  
    AND cs.created_at >= DATE_SUB(CURRENT_DATE, INTERVAL DAYOFMONTH(CURRENT_DATE)-1 DAY) 
    AND cs.created_at < DATE_ADD(LAST_DAY(CURRENT_DATE), INTERVAL + 1 DAY) 
GROUP BY u3.id 
ORDER BY COUNT(c3.id) DESC