优化复杂GROUP BY查询的性能

时间:2013-04-03 19:30:20

标签: mysql sql database-performance

有没有办法优化以下查询。大约需要11秒:

SELECT 
    concat(UNIX_TIMESTAMP(date), '000') as datetime, 
    TRUNCATE(SUM(royalty_price*conversion_to_usd*
             (CASE WHEN sales_or_return = 'R' THEN -1 ELSE 1 END)*
             (CASE WHEN royalty_currency = 'JPY' THEN .80 
                   WHEN royalty_currency in ('AUD', 'NZD') THEN .95 ELSE 1 END) )
    ,2) as total_in_usd
FROM 
    sales_raw 
GROUP BY
    date 
ORDER BY
    date ASC

做一个解释我得到:

1   SIMPLE  sales_raw   index   NULL    date    5   NULL    735855  NULL

3 个答案:

答案 0 :(得分:2)

这是对评论中问题的回答。它的格式更好:

过滤一组索引日期的示例意味着执行以下操作:

where date >= AStartDateVariable
and date < TheDayAfterAnEndDateVariable

如果日期字段中没有索引,请创建一个索引。

答案 1 :(得分:2)

你可以加快速度。您似乎在date上有一个索引。发生的事情是在索引中读取行,然后查找每一行。如果数据没有按日期字段排序,那么这可能不是最佳的,因为读取将基本上是随机页面。在原始表适合内存的情况下,这会导致称为“页面抖动”的情况。需要一条记录,从内存中读取页面(替换内存缓存中的另一页),下一次读取可能也会导致缓存未命中。

为了看看是否发生这种情况,我建议两件事之一。 (1)尝试删除date上的索引或将group by条件切换为concat(UNIX_TIMESTAMP(date), '000')。其中任何一个都应该删除索引作为一个因素。

根据你的附加评论,这不会发生,虽然索引的好处似乎偏小。

(2)您还可以展开索引以包括查询中使用的所有表。除日期外,索引还需要包含royalty_price,conversion_to_usd,sales_or_return和royalty_currency。这将允许索引完全满足查询,而无需在页面中查找其他信息。

您还可以咨询您的DBA,以确保您拥有与您的硬件功能相匹配的足够大的页面缓存。

答案 2 :(得分:0)

这是一个简单的查询组,甚至不涉及连接。我希望问题出在你正在使用的功能上。

请从简单的查询开始,只需检索日期和conversion_to_usd的总和。检查性能并逐步构建查询,始终检查性能。发现罪魁祸首不应该花很长时间。

Concats通常是缓慢的操作,但我想知道在sum之后截断是否会使优化器混乱。第二种情况可以通过依赖货币代码表和各自百分比的联接来代替,但是它并不明显,它会产生很大的不同。首先发现罪魁祸首。

您也可以使用正确的数量存储值,但会引入非规范化。