我仍然每天都在学习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中的include,但是它使我从2000个查询下降到1800个查询。
我看着group_by
,joins
并sum
但我不能让它工作。
我最接近工作的是
players = PlayerFixture.group("player_id").sum(:points)
然后我可以在其中进行查询,players[player.id]
但是无论如何都不会给我正确的结果,因为它没有考虑Gameweeks> Players> Player_fixtures关系。
如何减少正在执行的查询数量?我在freenode上继续#RubyOnRails,人们告诉我可以在1个查询中完成,但不会指向我任何方向或对我有帮助...
谢谢
花一些时间使用SQL。终于找到了可以帮助我的查询。我还发现了SQL视图以及如何通过Activerecord使用它们,这非常简洁。
最终成功查询
CREATE VIEW team_position_points AS
select teams.id as team_id, teams.team_name, players.type_name, sum(points) as points
from teams
inner join gameweeks on teams.id = gameweeks.team_id
inner join gameweeks_players on gameweeks.id = gameweeks_players.gameweek_id
inner join players on gameweeks_players.player_id = players.id
inner join player_fixtures on players.id = player_fixtures.player_id AND player_fixtures.gw_number = gameweeks.number
group by teams.id, players.type_name
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句