如何优化这个MySQL查询

时间:2010-05-27 17:18:02

标签: sql mysql query-optimization

当数据库很小时,这个查询工作正常,但是现在数据库中有数百万行,我意识到我应该先看看优化它。它正在查看超过600,000行并且正在使用where;使用临时;使用filesort(导致执行时间为5-10秒)。它正在使用字段'battle_type。'上的索引。

SELECT username, SUM( outcome ) AS wins, COUNT( * ) - SUM( outcome ) AS losses
FROM tblBattleHistory
WHERE battle_type =  '0' && outcome <  '2'
GROUP BY username
ORDER BY wins DESC , losses ASC , username ASC 
LIMIT 0 , 50

3 个答案:

答案 0 :(得分:5)

您似乎需要username, battle_type, outcomeusername, outcome, battle_type上的索引。

答案 1 :(得分:3)

首先要确保您拥有良好的索引(正如其他人所提到的那样)。

但是,看起来您正在为网页创建某种排行榜。我的第一个问题是 - 你真的需要实时执行这个查询吗?您可以在数据库中创建一个表(或在users表中添加一个胜负列),并使用此查询的结果并定期刷新它吗?

答案 2 :(得分:3)

让我们看看,你在做什么:

  1. 查找battle_type = 0且结果&lt;的行2
  2. 按用户名分组
  3. 计算聚合并将行折叠为不同的用户名
  4. 以dinamically计算字段排序
  5. 在第3步和第4步,你没有任何影响力。当前形式的第2步无法从任何索引中受益,因为outcome < 2是范围条件,索引(battle_type,结果,用户名)看起来非常诱人。

    假设outcome0,1,2,3...的枚举,您可以将范围条件更改为相等比较并从索引上获益(battle_type,outcome,username):

    SELECT username, SUM( outcome ) AS wins, COUNT( * ) - SUM( outcome ) AS losses
    FROM tblBattleHistory
    WHERE battle_type = 0 AND outcome IN (0, 1)
    GROUP BY username
    ORDER BY wins DESC , losses ASC , username ASC 
    LIMIT 0 , 50
    

    如果outcome不是枚举,那么(battle_type,outcome)的索引就可以了。因为battle_type是复合索引中的前缀,所以(battle_type)上的索引现在只是过量。

相关问题