0

このクエリは問題なく実行されます。

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は aLEFT JOINを実行し、 をjoins実行しINNER JOINます。joinsRails から吐き出されるクエリ ( for ) は次のとおりです。

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

も問題なく実行され、2 倍の時間がかかります。

players_to_teams経由でレコードをソートできる効率的な方法はありplayersますか? のインデックスがありFirstNameますplayers

編集

クエリを適切に実行するには、かなりの最適化が必要であることが判明しました。クエリの分割は、データの再構築やクエリのカスタマイズを除けば、最善の解決策でした

4

2 に答える 2

0

また、2(3)クエリに分割することを検討することもできます。最初に-結合でソートしてIDを取得するには:

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

2番目(内部には2つのクエリが含まれています)-PlayersToTeamsプレーヤーがプリロードされた状態で取得します。

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

したがって、その後、players_to_teamsプレーヤーがロードされて初期化された状態で完全に初期化されます。

于 2012-04-11T21:20:19.557 に答える
0

注意すべきことの 1 つincludeは、プリロードを行うために 2 番目の db アクセスを追加することです。それがどのように見えるかを確認する必要があります(fromに大きなINステートメントが含まれている必要があります)。player_idsplayers_to_teams

の使用を避ける方法についてincludeは、 の名前だけが必要な場合はplayers、次のようにできます。

PlayersToTeam.select("players_to_teams.id, players.FirstName AS player_name").joins(:player).limit(10).order("players.FirstName")
于 2012-04-11T20:50:38.343 に答える