在查询中使用聚合函数需要花费大量时间

时间:2018-01-15 12:18:30

标签: php mysql mysqli query-performance

表有100 000条记录,使用聚合函数需要20-21秒。如何优化此查询?

SELECT source, sum(product_price*quantity) AS price 
FROM `sheet` 
WHERE source !='' 
GROUP BY source 
ORDER BY `price` DESC        

我还在表格中使用了索引

ALTER TABLE `dbname`.`sheet` ADD INDEX `reprting_module` (`source`(30));  

这是解释查询后的输出

enter image description here

2 个答案:

答案 0 :(得分:1)

首先,您要求MySQL服务器在此查询中进行一些计算,然后对结果进行排序。这需要一些时间。它必须检查表格的每一行或几乎每一行。将这些操作瞬间完成是没有魔力的。

其次,您的WHERE source != ''过滤器可能会破坏您的索引。您可以尝试使用WHERE source > ''。这将允许MySQL的查询规划器随机访问您的索引,然后按顺序扫描它。

第三,您的子集source索引(source(30))无助于提升效果。

第四,您可以尝试在这些列上创建覆盖索引的化合物:

    ALTER TABLE dbname.sheet 
      ADD INDEX `reprting_module` (source, product_price, quantity);

然后像这样编写你的查询:

SELECT source, SUM(product_price*quantity) AS price 
  FROM sheet 
 WHERE source > '' 
 GROUP BY source 
 ORDER BY SUM(product_price*quantity) DESC  

如果你很幸运,这会更快一些。为什么?因为MySQL可以通过随机访问索引到第一个非空source值来满足整个查询,然后依次扫描索引来执行计算。

请注意,如果您使用

,我显示的查询,以及我显示的索引,确实非常快
     WHERE source = 'some-particular-value'

缩小计算范围。

答案 1 :(得分:0)

"前缀"索引,例如INDEX(source(30)),实际上是无用的。请提供SHOW CREATE TABLE。如果source可能是VARCHAR(255)或更小,只需添加INDEX(source)但这可能在此处没用,因为需要阅读大部分表格。

你有多少内存? innodb_buffer_pool_size的价值是多少?桌子有多大(GB)?这些结合起来询问您是CPU绑定还是I / O绑定,以及简单的调整修复是否可以将其从I / O更改为CPU,从而可能将其加速到2秒。 (仅仅10万行,20秒似乎非常高。)