0

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

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 分钟。正常吗?有没有办法优化这个查询?

描述“表”并解释选择

我认为DATE_FORMAT这里的功能真的会扼杀性能..这里有什么提示吗?它运行大约 58 秒。

4

2 回答 2

1

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

您的查询对事务有一个 LEFT-JOIN,但随后 b.noticeID 不为空。两者的组合导致双方都需要正常的“JOIN”或“INNER JOIN”含义。

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

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

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

修订

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

尝试索引

INDEX on ...(DueDate、状态、IsAward、TypeOfNotice、ValidIndicator)

此外,为了澄清您的查询中的 alias.fields。有时您明确引用“a”。别名和其他时候,没有别名。对于在您之后进行查询的其他人,或其他试图提供帮助的人。它可以更轻松地显式引用具有正确别名的所有字段,以防止来自哪个表的哪些列不明确。是的,你在这里提供了你的表结构,但未来可能比必须继续回顾结构更容易。

于 2012-05-14T11:06:23.103 回答
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

第二个可能更快。

你为什么不按截止日期分组?然后你可以省略 DATE_FORMAT(),但我猜这只是小菜一碟。如果您省略它,ORDER BY则也没有必要,因为它与 GROUP BY 有牵连。

除此之外,您无能为力。

于 2012-05-14T11:06:07.890 回答