2016-11-29 200 views
0

Im使用下面的查询来计算每个公司排名前5的费用并对它们进行排序。目前该表有大约300万行,需要大约8秒才能正确执行。我正在寻找一种方法来加速这一点。如何加速此SUM查询?

SELECT 
    SUM(cost) as sumw, 
    company FROM cost 
WHERE 
    datetime BETWEEN '2016-10-01' AND '2016-12-01' 
GROUP BY company 
ORDER BY sumw desc 
LIMIT 5; 

datetime有一个索引。

说明:

1 SIMPLE cost NULL ALL datetime NULL NULL NULL 3204715 50.00 Using where; Using temporary; Using filesort 

CREATE

CREATE TABLE `cost` (
    `id` bigint(8) unsigned NOT NULL AUTO_INCREMENT, 
    `company` varchar(45) DEFAULT NULL, 
    `cost` bigint(8) unsigned DEFAULT NULL, 
    `datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `datetime` (`datetime`) 
) ENGINE=InnoDB AUTO_INCREMENT=3335830 DEFAULT CHARSET=utf8; 
+0

添加硬件;或在查询之前每天/每小时生成总计。 SQL看起来像它一样高效。也许会把字符串转换成日期,所以它不必隐含地做到这一点,但我无法想象这会给你带来多大的收益。在MySQL之外,我可能会提出一个带周期性刷新的物化视图,但MySQL没有。 – xQbert

+1

习惯上要求SQL性能有助于显示涉及的表定义,包括索引。显示'EXPLAIN'的输出也是一个好主意。 –

+0

补充信息@ O.Jones – Ray

回答

1

一个复合索引您cost表上(datetime, company, cost)可能能够改善查询的性能。值得一试,特别是如果cost表中有许多其他列未涉及此查询。

请注意查询中的内容。

datetime BETWEEN '2016-10-01' AND '2016-12-01' 

检索所有与1 - 10月-2016午夜到1 - 12月-2016午夜包容值的行。您可能想要

datetime >= '2016-01-01' AND datetime < '2016-12-01' 

如果您要处理10月和11月的数据。这第二个公式在使用您的指数时比第一个公式效率更低。

+0

查询正在使用正确。电话日期为此问题添加。 – Ray

+0

添加索引减少了2秒 – Ray

+0

首先添加一个复合索引以加快查询** ALTER TABLE'cost'添加键idx_date_company('datetime','company'); **并再次测试。请发布新的解释 –

1

您的查询是按公司计算的结果,因此它需要公司专栏的索引。

ALTER TABLE cost ADD INDEX(company); 

希望这会有所帮助。

+0

尊重,这是不正确的。 MySQL查询可以(截至2016年底)仅利用单个索引。此提问者查询的主要部分是'datetime'列中的范围搜索。 –