2012-04-11 6 views
0

Diese Abfrage führt gerade fein:Rails Abfrage Drosseln auf beinhaltet

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

Diese Abfrage mein ganzes System führt zum Stillstand zu kommen:

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

Hier sind die Modelle:

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 

Soweit ich das beurteilen kann, macht die includes eine LEFT JOIN und joins macht a n INNER JOIN. Die Abfrage ausspucken (für joins) von Rails ist:

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 

, die gerade fein auf der Kommandozeile ausgeführt wird.

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 

führt auch gut, es dauert nur doppelt so lange.

Gibt es eine effiziente Möglichkeit, die players_to_teams Datensätze über players zu sortieren? Ich habe einen Index auf FirstName für players.

EDIT

Schaltet die Abfrage erforderlich schwere Optimierung heraus anständig auch nur die Hälfte laufen. Das Aufteilen der Abfrage war die beste Lösung, um die Daten neu zu strukturieren oder die Abfrage anzupassen

+1

Haben alle Ihre Join-Schlüssel Indizes? – DGM

+0

Wenn Sie "quietschen halt" sagen, was genau passiert? –

+0

'quietschender Halt' bedeutet, dass bei Verwendung der Rails-Konsole das Terminalfenster nur sitzt und dreht, bis ich es ctrl-c. Ich gebe es normalerweise ein paar Minuten, bevor ich es aufgäbe. –

Antwort

0

Sie auch interessieren könnten es in 2 (3) Abfragen aufzuteilen. Erste - zu ids erhalten durch Sortieren mit Verknüpfungen:

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

Sekunde (die im Inneren ist enthält 2 Abfragen) - PlayersToTeams mit Spielern vorbelastet zu bekommen.

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

So nach, dass Sie voll players_to_teams mit Spielern geladen und initialisiert initialisiert wird.

0

Eine Sache zu beachten ist, dass include einen zweiten DB-Zugriff hinzufügen wird, um das Vorladen durchzuführen. Sie sollten überprüfen, wie das aussieht (es sollte eine große IN Erklärung auf der player_ids von players_to_teams enthalten).

Was, wie include zu vermeiden, verwenden, wenn Sie nur den Namen von players benötigen, können Sie es wie folgt tun:

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