2012-05-14 105 views
0

有没有什么办法来优化下面的查询?MySQL查询优化总和..案例

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秒。

+1

请为您的查询发布'EXPLAIN'输出,以及两个表的模式。 – eggyal

回答

1

该查询看起来很简单,因为它可以...除了SUM(IF())实例外。

您的查询具有LEFT JOIN交易,但是然后有b.noticeID不为空。两者的结合在双方都需要正常的“JOIN”或“INNER JOIN”含义。

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

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

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

修订

你也许可以为呈现在您的查询中使用的元素的多指标的优势,因此查询不必真正去的页面数据看整个记录中的单个元素。由于数据将成为索引键的一部分,因此查询可以直接使用,而不需要转到页面。

尝试对

索引的索引...(交货期,状态,IsAward,TypeOfNotice,ValidIndicator)

此外,澄清alias.fields的查询。有时你明确提到“a”。别名和其他时间,没有别名。对于在您之后处理查询的其他人或尝试提供帮助的其他人。它使得显式引用具有适当别名的所有字段更容易,以防止来自哪个表的哪些列含糊不清。是的,你在这里提供了你的表格结构,但未来可能会让事情变得更容易,而不必回头看结构。

+0

我在日期范围内有428173条记录.. 我忽略了group by子句,但仍然没有快乐。我给了我一个单行结果。我还使用了“组由交货期”,但它给了我一个意想不到的结果,每一行都有相同的日期,但不同时间.. –

+0

@ user877880,OK,是有道理的,然后上的日期是一个日期/时间戳记,你显然希望基于“每日”基础。也修改了答案。 – DRapp

+0

但是,您对INNER JOIN的建议花费了6秒的查询痛苦。我只是使用Date()函数而不是DATE_FORMAT,这给了我一个比旧查询更好的性能。 –

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有关。

除此之外,你可以做的不多。