Rails查询包含的chokes

时间:2012-04-11 19:22:27

标签: mysql ruby-on-rails

此查询执行得很好:

p = PlayersToTeam.select("id").joins(:player).limit(10).order("players.FirstName")

此查询导致我的整个系统突然停止:

p = PlayersToTeam.select("id").includes(:player).limit(10).order("players.FirstName")

以下是模型:

class PlayersToTeam < ActiveRecord::Base
  belongs_to :player
  belongs_to :team

  accepts_nested_attributes_for :player
end

class Player < ActiveRecord::Base
  has_many :players_to_teams
  has_many :teams, through: :players_to_teams
end

据我所知,includes执行LEFT JOINjoins执行INNER JOIN。来自Rails的查询吐出(对于joins)是:

SELECT players_to_teams.id FROM `players_to_teams` INNER JOIN `players` ON `players`.`id` = `players_to_teams`.`player_id` ORDER BY players.FirstName LIMIT 10

在命令行上执行得很好。

SELECT players_to_teams.id FROM `players_to_teams` LEFT JOIN `players` ON `players`.`id` = `players_to_teams`.`player_id` ORDER BY players.FirstName LIMIT 10

也执行得很好,只需要两倍的时间。

我是否可以通过players_to_teamsplayers条记录进行排序?我FirstName的{​​{1}}索引。

修改

结果查询需要进行大量优化才能正常运行一半。拆分查询是重构数据或自定义查询的最佳解决方案

2 个答案:

答案 0 :(得分:0)

需要注意的一点是include将添加第二个db访问权来进行预加载。您应该检查一下它的内容(它应该包含来自IN的{​​{1}}的大player_ids条声明。

至于如何避免使用players_to_teams,如果您只需要include中的名称,则可以这样做:

players

答案 1 :(得分:0)

您也可以考虑将其拆分为2(3)个查询。首先 - 通过连接排序获取ID:

players_to_teams = PlayersToTeam.select("id").joins(:player).limit(10).order("players.FirstName")

第二个(内部包含2个查询) - 预先加载玩家PlayersToTeams

players_to_teams = PlayersToTeam.include(:player).where(:id => players_to_teams.map(&:id))

之后,您将完全初始化players_to_teams并加载并初始化播放器。