这是一个查询,用于汇总每个玩家的游戏结果并显示符合条件的玩家。
select *,
(kills / deaths) as killdeathratio,
(totgames - wins) as losses
from (select gp.name as name,
gp.gameid as gameid,
gp.colour as colour,
Avg(dp.courierkills) as courierkills,
Avg(dp.raxkills) as raxkills,
Avg(dp.towerkills) as towerkills,
Avg(dp.assists) as assists,
Avg(dp.creepdenies) as creepdenies,
Avg(dp.creepkills) as creepkills,
Avg(dp.neutralkills) as neutralkills,
Avg(dp.deaths) as deaths,
Avg(dp.kills) as kills,
sc.score as totalscore,
Count(* ) as totgames,
Sum(case
when ((dg.winner = 1 and dp.newcolour < 6) or
(dg.winner = 2 and dp.newcolour > 6))
then 1
else 0
end) as wins
from gameplayers as gp,
dotagames as dg,
games as ga,
dotaplayers as dp,
scores as sc
where dg.winner <> 0
and dp.gameid = gp.gameid
and dg.gameid = dp.gameid
and dp.gameid = ga.id
and gp.gameid = dg.gameid
and gp.colour = dp.colour
and sc.name = gp.name
group by gp.name
having totgames >= 30
) as h
order by totalscore desc
现在我不太确定最好的方法是什么,但您认为优化此查询的方法是什么?
我运行 Q6600 @ 2.4ghz、4gb 内存、64 位 Linux Ubuntu 9.04 系统,这个查询最多可能需要 6.7 秒才能运行(我有一个巨大的数据库)。
我也想对结果进行分页,在此查询之上执行额外的条件太慢了....
我使用 django 作为前端,所以任何包括使用 python +/- django 方法的方法都会很棒。也欢迎 MySQL、Apache2 调整。当然,我愿意更改查询以使其运行得更快。
感谢阅读我的问题;期待阅读您的答案!
编辑:解释查询结果
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 783 Using filesort
2 DERIVED sc ALL name,name_2 NULL NULL NULL 2099 Using temporary; Using filesort
2 DERIVED gp ref gameid,colour,name name 17 development.sc.name 2
2 DERIVED ga eq_ref PRIMARY,id,id_2 PRIMARY 4 development.gp.gameid 1 Using index
2 DERIVED dg ref gameid,winner gameid 4 development.ga.id 1 Using where
2 DERIVED dp ref gameid_2,colour gameid_2 4 development.ga.id 10 Using where
最佳答案
首先,SQL 格式错误。最明显的错误是每个 AS
子句之前的行拆分。第二个明显的问题是使用隐式连接而不是显式使用 INNER JOIN ... ON ...
。
现在回答实际问题。
在不知道数据或环境的情况下,我首先要看的是一些 MySQL 服务器设置,例如 sort_buffer
和 key_buffer
。如果您没有更改任何这些,请继续阅读它们。默认值非常保守,通常可以提高到默认值的十倍以上,尤其是在像您这样的大型熨斗上。
回顾之后,我将运行部分查询以查看速度以及 EXPLAIN
所说的内容。索引的影响可能是深远的,但 MySQL 有一个“手指和脚趾”问题,它不能在每个表中使用多个索引。带过滤功能的 JOIN
可能需要两个。所以它必须下降到行扫描以进行其他检查。但话虽如此,将查询切分并尝试不同的组合会告诉您它从哪里开始出现问题。
现在您将了解“临界点”可能在哪里:这是一些原始数据大小的小幅增加,例如需要提取多少,将导致性能大幅下降,因为某些内部结构变得太大了。此时,您可能希望增加临时表的大小。请注意,这种优化有点像魔法。 :-)
然而,还有另一种方法:反规范化。在一个简单的实现中,定期调度的脚本会不时地运行这个昂贵的查询,并将数据插入一个单独的表中,其结构更接近您想要显示的内容。这种方法有多种变体。可以在应用程序中或使用表触发器随时保持最新状态。在另一个极端,您可以允许您的应用程序偶尔运行昂贵的查询,但将结果缓存一会儿。如果很多人经常调用它,这是最有效的:即使是每秒运行 15 次的请求的 2 秒缓存也会显示出明显的改进。
您可以找到生成相同数据的方法,方法是运行六个查询,每个查询返回一些数据,然后对数据进行后处理。您还可以运行返回更多数据的原始查询版本(这可能会更快,因为它进行的过滤更少)并对其进行后处理。我多次发现五个更简单、更小的查询比一个试图完成所有操作的大查询要快得多——一个数量级,有时是两个数量级。
关于python - 优化此 MySQL 查询的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1191105/