此查询执行得很好:
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 JOIN
而joins
执行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_teams
对players
条记录进行排序?我FirstName
的{{1}}索引。
修改
结果查询需要进行大量优化才能正常运行一半。拆分查询是重构数据或自定义查询的最佳解决方案
答案 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
并加载并初始化播放器。