2017-07-19 89 views
1

我们只有一个包含数百万行的表,其中此查询需要138秒的时间才能在缓冲池大小为25G的服务器上运行,服务器本身使用的是带有SSD驱动器的Linux。Mysql Group By和性能问题

我想知道是否有人可以建议任何改进MySQL设置或查询本身,这将减少运行时间。我们只有8个大的member_id有这个性能问题,其余的只有5秒。我们针对汇总报告运行多个汇总表。

select * 
from (
SELECT distinct account_name AS source,SUM(royalty_amount) AS total_amount 
FROM royalty_stream 
WHERE member_id = '1050705' 
    AND deleted = 0 
    AND period_year_quarter >= '2016_Q1' 
    AND period_year_quarter <= '2016_Q2'  
GROUP BY account_name 
ORDER BY total_amount desc 
LIMIT 1 
) a 
+0

什么是表的架构为何? – Jacobm001

+0

解释输出是什么? – Jacobm001

+0

“GROUP BY”查询中DISTINCT的用途是什么? – axiac

回答

2

我看到了一些明显的改进。

子选择

不要使用子查询。这不是一个大问题,但在这里增加开销是没有意义的。

使用鲜明

是在distinct这里真正需要的?由于你正在分组,它应该是不必要的开销。

数据存储实践

period_year_quarter评估将是一个障碍。不幸的是,字符串比较是你能做的较慢的事情之一。如果您有能力更新数据结构,我强烈建议您将period_year_quarter分解为两个不同的整数字段。一年一季,一季季。

是royalty_amount实际存储为一个数字,还是你让数据库隐式转换它每次?如果是这样(令人惊讶的常见错误)将其转换为数字也将有所帮助。

索引

你没有解释是在此表中哪些索引。我希望你至少在member_id上有一个。如果不是,它肯定应该被索引。

我会进一步推荐(member_id, period_year_quarter)的索引。如果您从上一节中获得了我的建议,那应该是(member_id, year, quarter)


select 
    account_name as source 
    , sum(royalty_amount) as total_amount 
from 
    royalty_stream 
where 
    member_id    = '1050705' 
    and deleted    = 0 
    and period_year_quarter between '2016_Q1' and '2016_Q2' 
group by 
    account_name 
order by 
    total_amount desc 
limit 1 
+0

我也试着在索引中使用account_name。只有数据会告诉我们这是不是一个好主意。 –

+0

@SamHartman:把它放在自己的索引中。既然你不符合资格,它不会从索引中获得巨大的收益。 – Jacobm001

+0

字符串比较没有太大的障碍。索引的正确使用是最重要的 - 但你的其他观点都是有效的。 – Strawberry