我正在开发一个 Rails 项目并遇到性能问题。这是简化的数据库架构
table gaming_platforms ( ~5 rows) id table games ( ~10k rows) id gaming_platform_id winner (black or white or n/a) black_id => online_players.id white_id => online_players.id table online_players ( ~1k rows) id gaming_platform_id username
现在给定一个用户名,我想显示名字与输入匹配的玩家,没有。他们参加的比赛、获胜或失败的比赛。
我创建了 3 个 View 来避免 1+n 问题。
create or replace view online_player_games as select online_players.id as online_player_id, count(*) as games from games left join online_players on games.gaming_platform_id = online_players.gaming_platform_id and (games.black_id = online_players.id or games.white_id = online_players.id) group by online_players.id; create or replace view online_player_won_games as select online_players.id as online_player_id, count(games.id) as games from online_players left join games on games.gaming_platform_id = online_players.gaming_platform_id and ((games.winner = 1 and games.black_id = online_players.id) or (games.winner = 2 and games.white_id = online_players.id)) group by online_players.id; create or replace view online_player_lost_games as select online_players.id as online_player_id, count(games.id) as games from online_players left join games on games.gaming_platform_id = online_players.gaming_platform_id and ((games.winner = 2 and games.black_id = online_players.id) or (games.winner = 1 and games.white_id = online_players.id)) group by online_players.id;
在不使用任何索引的情况下,查询这些 View 需要超过 20 秒的时间。查询看起来很复杂。我不确定应该创建哪些索引。非常欢迎任何意见或建议。
最佳答案
我认为您的设计存在一些一般的可扩展性问题。当您添加游戏和用户时,从 I/O 角度来看,您计算输赢的方式将大大增加数据库的工作量。
我建议创建一个名为 player_record
的表,其中包含玩家 ID、获胜次数、失败次数。然后创建一个在游戏结束时调用的存储过程。 (例如 spGameFinished(game_id, Winner,..);
)该存储过程将负责执行已完成的游戏所需的任何任务,其中一项任务是更新该 player_record
表根据谁被指定为获胜者。我假设当游戏开始时,您将游戏放入 2 个玩家 ID 中,但如果您不这样做,那么存储过程也必须在游戏完成时将这些 ID 放入其中。
一旦到位,收集赢/输信息所需的查询就很简单了。这还允许您将游戏的存储要求与玩家记录分开管理。 (即您可以删除非常旧的游戏而不影响用户记录)
关于Mysql查询优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1828653/