MySQL查询优化总和..案例

时间:2012-05-14 10:24:50

标签: mysql query-optimization

有没有办法优化下面的查询?

SELECT 
DATE_FORMAT(a.duedate,'%d-%b-%y') AS dte, 
duedate, 
SUM(CASE WHEN (typeofnotice='ddat' AND STATUS='open') THEN 1 ELSE 0 END) AS 'DDatOpen', 
SUM(CASE WHEN (typeofnotice='ddat' AND STATUS='closed') THEN 1 ELSE 0 END) AS 'DDatClosed', 
SUM(CASE WHEN (b.action='tagunchanged' AND STATUS='closed') THEN 1 ELSE 0 END) AS 'DDatUnchanged',
SUM(CASE WHEN (typeofnotice='rss' AND validindicator IS NULL AND STATUS='open') THEN 1 ELSE 0 END) AS 'RSSValidation', 
SUM(CASE WHEN (typeofnotice='rss' AND validindicator=1 AND STATUS='open') THEN 1 ELSE 0 END) AS 'RSSValidOpen', 
SUM(CASE WHEN (typeofnotice='rss' AND validindicator=1 AND STATUS='closed') THEN 1 ELSE 0 END) AS 'RSSValidClosed', 
SUM(CASE WHEN (typeofnotice='rss' AND validindicator=0) THEN 1 ELSE 0 END) AS 'RSSInvalid', 
SUM(CASE WHEN (typeofnotice='copernic' AND validindicator IS NULL AND STATUS='open') THEN 1 ELSE 0 END) AS 'CopernicValidation', 
SUM(CASE WHEN (typeofnotice='copernic' AND isaward=1 AND validindicator=1 AND STATUS='open') THEN 1 ELSE 0 END) AS 'CopernicValidAwardOpen', 
SUM(CASE WHEN (typeofnotice='copernic' AND isaward=1 AND validindicator=1 AND STATUS='closed') THEN 1 ELSE 0 END) AS 'CopernicValidAwardClosed', 
SUM(CASE WHEN (typeofnotice='copernic' AND isaward=1 AND validindicator=0) THEN 1 ELSE 0 END) AS 'CopernicInvalidAward', 
SUM(CASE WHEN (typeofnotice='copernic' AND isaward=0 AND validindicator=1 AND STATUS='open') THEN 1 ELSE 0 END) AS 'CopernicOpportunityValidOpen', 
SUM(CASE WHEN (typeofnotice='copernic' AND isaward=0 AND validindicator=1 AND STATUS='closed') THEN 1 ELSE 0 END) AS 'CopernicOpportunityValidClosed', 
SUM(CASE WHEN (typeofnotice='copernic' AND isaward=0 AND validindicator=0) THEN 1 ELSE 0 END) AS 'CopernicOpportunityInvalid', 
SUM(CASE WHEN (typeofnotice='copernic' AND STATUS='limited') THEN 1 ELSE 0 END) AS 'CopernicLimitation', 
SUM(CASE WHEN ((validindicator IS NULL OR validindicator = 1) AND STATUS='open') THEN 1 ELSE 0 END) AS 'TotalNotices', 
SUM(CASE WHEN (validindicator=1 AND STATUS='closed') THEN 1 ELSE 0 END) AS 'TotalCompleted', 
SUM(CASE WHEN (validindicator=0 AND (typeofnotice='wget' OR typeofnotice='copernic' OR typeofnotice='rss')) THEN 1 ELSE 0 END) AS 'TotalInvalid'
FROM tblNotices AS a LEFT JOIN tblTransactions AS b 
ON a.id = b.noticeid WHERE b.noticeid IS NOT NULL
WHERE duedate >= '2011-04-04 00:00:00'  AND  a.duedate <= '2012-05-08 24:00:00' 
GROUP BY dte 
ORDER BY dueDate ASC;

tblTransactions有150万行 tblNotices有900k行。

查询运行约1分钟。这是正常的吗?有没有办法优化这个查询?

Describe 'table' and Explain Select

我认为此处的DATE_FORMAT功能确实会影响性能..这里有什么提示吗?它运行大约58秒。

2 个答案:

答案 0 :(得分:1)

除了SUM(IF())实例之外,查询看起来很简单。

您的查询对事务具有LEFT-JOIN,但是b.noticeID不为null。两者的组合导致双方都需要正常的“JOIN”或“INNER JOIN”。

至于你的Where子句,我会确保你在截止日期有一个简单的索引。你的表显示了一个“MUL”(多键)索引,我会确保截止日期是该键的第一部分,或者至少有一个索引作为第一个字段使用duidate。

接下来,你的小组由。由于您是按截止日期的日期格式进行分组,因此我只会根据duedate(匹配表索引)离开组。无论如何,视觉格式化的字符串将跟随骑行。因为您的Order By也是基于duedate(而不是相当格式化的字符串版本),所以应该很好。

至于查询本身的日期范围...提供的范围内有多少条记录。

REVISION

您可以利用查询中使用的元素的多部分索引,这样查询就不必实际转到页面数据来查看整个记录中的各个元素。由于数据将成为索引键的一部分,因此查询可以直接使用它,而不需要转到页面。

尝试

上的索引

INDEX on ...(DueDate,status,IsAward,TypeOfNotice,ValidIndicator)

另外,为了澄清查询中的alias.fields。有时您明确引用“a”。别名和其他时间,没有别名。对于您或其他人尝试提供帮助后处理查询的其他人。它使得使用适当的别名显式引用所有字段变得更容易,以防止来自哪个表的哪些列的歧义。是的,你在这里提供了你的表格结构,但是未来可以比不断回顾结构更容易。

答案 1 :(得分:0)

嗯,那个

FROM tblNotices AS a LEFT JOIN tblTransactions AS b 
ON a.id = b.noticeid WHERE b.noticeid IS NOT NULL

相同
FROM tblNotices AS a INNER JOIN tblTransactions AS b 
ON a.id = b.noticeid

第二个可能更快。

你为什么不通过duedate分组?然后你可以省略DATE_FORMAT(),但我想这只是花生。如果省略它,ORDER BY也没有必要,因为它与GROUP BY有牵连。

除此之外,你无能为力。