优化MySQL脚本

时间:2018-08-16 13:33:49

标签: mysql query-optimization

我已经开始了新工作,他们正在使用MySQL作为其主要数据库。

我更习惯于MSSQL,并且想知道下面的语句是否可以优化,因为它花费了10分钟!

在此先感谢您提供任何帮助。

SELECT 
CAST(DATE_FORMAT(created_at, '%Y-%m-%d %k:%i:00') 
AS DATETIME) AS 'Date', 
COUNT(*) AS Count 
FROM 
db 
WHERE 
created_at BETWEEN NOW() - INTERVAL 5 HOUR AND NOW() 
AND status = 'Accepted' 
GROUP BY CAST(DATE_FORMAT(created_at, '%Y-%m-%d %k:%i:00') 
AS DATETIME)

3 个答案:

答案 0 :(得分:0)

不知道为什么要在select或group by中进行转换,而将最后一行替换为:

GROUP BY DATE_FORMAT(created_at, '%Y-%m-%d %k:%i')

如果这没有太大帮助,请在该命令前添加'EXPLAIN',然后检查输出。如果您无法通过explain-prefix弄清楚,请将其张贴在此处,以便有人可以为您提供有关索引的建议。

答案 1 :(得分:0)

索引(status, created_at)将优化此查询的WHERE部分(范围之前的常量)。

您的分组似乎表明您想按created_at的分钟进行分组。基于此表达式创建生成的列并将其附加到索引将有助于此子句的GROUP BY部分(并且GROUP BY应该引用此生成的列而不是表达式)。

alter table db add minute bigint unsigned as (to_seconds(created_at) div 60),
                 add index status_created_at_min (status, created_at, minute);

以及结果查询:

SELECT 
CAST(DATE_FORMAT(created_at, '%Y-%m-%d %k:%i:00') 
AS DATETIME) AS 'Date', 
COUNT(*) AS Count 
FROM 
db 
WHERE 
created_at BETWEEN NOW() - INTERVAL 5 HOUR AND NOW() 
AND status = 'Accepted' 
GROUP BY minute;

答案 2 :(得分:0)

这可能会加快速度,因为它将处理WHERE

INDEX(status, created_at)   -- in this order

如果您创建了一个“生成的”列(如danblack建议的那样),则可以通过在查询和索引中仅使用 生成的列来进行进一步操作。这样,它将成为“覆盖”索引,因此查询将完全在索引中执行:

INDEX(status, minute)   -- in this order

如果那还不够...

带有“报告”的大表通常会受益于创建和维护“摘要表”。与其他供应商不同,没有内置机制可以执行此操作。参见this