开发者

Optimise ActiveRecord Query

I've been working through optimising my Rails application but I'm stuck one particular query:

def self.random_selection(n)
  items = scoped(:joins => "JOIN (SELECT id
      FROM #{table_name}
      WHERE medias_count > 0
      ORDER BY RAND()
      LIMIT #{n.to_i}
    ) AS random_ids
    ON #{table_name}.id = random_ids.id"
  )
  items.each do |genre|
    genre.medias.sort! do |x,y|
      y.vote_total <=> x.vote_total
    end
  end
  items
end

The idea is that it will select a number of random genres that have media within them. Once selected, it will then sort on the highest rated media, I think take that "top media" and use it within the view.

This is quite an expensive, ugly query and I'd like some approaches I could take on optimising it.

Could I roll the selection of medi开发者_如何学Pythonas into the original query?

Should I approach this from the other direction and select random high rated medias and fetch the genre from them? (also acceptable, but if it doesn't offer any improvement then theirs no point)

I'm using Rails 3, Ruby 1.9.2 and MySQL with InnoDB.


My solution

class Genre
  scope :having_media, where('medias_count > 0')
  scope :random, lambda { |limit| where(:id => random_ids(limit)) }

  def self.random_ids(limit)
    having_media.select('id').sample(limit).map(&:id)
  end

  def self.random_selection(limit)
    random(10).includes(:medias).each do |genre|
      genre.medias.sort! do |x,y|
        y.vote_total <=> x.vote_total
      end
    end   
  end
end

class Media
  scope :voted_higher, reorder('vote_total desc')
end

@random_genres = Genre.random_selection(10)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜