我仍然每天都在学习 ruby、rails 和 ActiveRecord。现在我正在通过我正在构建的一个新的小应用程序学习 SQL,但问题是我的应用程序的主视图目前每次页面刷新大约 2000 次查询,oouuuppps。
所以现在我知道我的数据库中有所有必需的信息并且我可以正确显示它们,现在是我优化它们的时候了,但我只是不知道从哪里开始说实话。
这些是我的模特协会
class League < ActiveRecord::Base
belongs_to :user
has_many :league_teams
has_many :teams, :through => :league_teams
end
class Team < ActiveRecord::Base
has_many :gameweeks
has_many :league_teams
has_many :leagues, :through => :league_teams
end
class Gameweek < ActiveRecord::Base
belongs_to :team
has_and_belongs_to_many :players
has_and_belongs_to_many :substitutes, class_name: "Player", join_table: "gameweeks_substitutes"
belongs_to :captain, class_name: "Player"
belongs_to :vice_captain, class_name: "Player"
end
class Player < ActiveRecord::Base
serialize :event_explain
serialize :fixtures
serialize :fixture_history
has_many :gameweeks, class_name: "captain"
has_many :gameweeks, class_name: "vice_captain"
has_and_belongs_to_many :gameweeks
has_many :player_fixtures
end
所以这是我的控制器:
@league = League.includes(teams: [{gameweeks: [{players: :player_fixtures} , :captain]}]).find_by(fpl_id:params[:fpl_id])
@teams = @league.teams
@defense_widget_leaderboard = @league.position_based_leaderboard_stats(@teams, ['Defender', 'Goalkeeper'])
这是我的联盟模型中的一种方法:
def position_based_leaderboard_stats(teams,positions_array)
leaderboard = []
teams.each do |team|
position_points = 0
gameweeks = team.gameweeks
gameweeks.each do |gameweek|
defense = gameweek.players.where(type_name:positions_array)
defense.each do |player|
player.player_fixtures.where(gw_number: gameweek.number).each do |p|
position_points += p.points
end
end
end
leaderboard << [team.team_name,position_points]
end
return leaderboard.sort_by {|team| team[1]}.reverse
end
我有 4 种方法看起来或多或少与上面的方法相同。每个人都在做 300 到 600 个查询。
据我所知,它是 N+1 查询的典型案例。我试图减少 @league 中的包含,但它让我从 2000 个查询减少到 1800 个查询。
我调查了group_by
,joins
但sum
我无法让它工作。
我最接近工作的是这个
players = PlayerFixture.group("player_id").sum(:points)
然后我可以通过做查询,players[player.id]
但这并没有给我正确的结果,因为它没有考虑到 Gameweeks > Players > Player_fixtures 关系。
如何减少我正在执行的查询数量?我在freenode上继续#RubyOnRails,人们告诉我它可以在1个查询中完成,但不会向我指出任何方向或帮助我......
谢谢