I need some help optimizing the following method. The queries have become too costly as my database has grown in size to 3K users and 100K workouts. Unfortunately my SQL skills are rudimentary.
The method returns the rank of a given workout against other workouts by people of the same gender, and the total number of workouts for that gender. There are other applicable conditions to the workouts which I have removed to simplify this sample:
Class Person
has_many :workouts
named_scope :men, :conditions => {:male => true}
end
开发者_JS百科
Class Workout
belongs_to :person
named_scope :by, lambda {|person_id| {:conditions => {:person_id => person_id}}}
def rank_by_gender
people = Person.men.collect{|p| p.id}
{ :place =>
Workout.by(people).count(:conditions => ["time < ?", self.time]) + 1
:entries =>
Workout.by(people).count() }
end
end
Person.men now returns several thousand records. Is there a way to combine that query with the count query, possibly by using a join on the people table with on the :male attribute?
Is there a way to put a condition on the Person association into the conditions passed to the count method?
Beyond that, does anyone see other ways to reduce the size and time of database queries in this method?
This should work for you:
{
:place => Workout.joins(:person).where(["`workouts`.time < ? AND `people`.male = ?", self.time, true]).size,
:entries => Workout.joins(:person).where(:people => {:male => true}).size
}
精彩评论