2011-05-26 50 views
4

我已经通过优化我的Rails应用程序工作,但我被困在一个特定的查询:优化ActiveRecord的查询

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 

的想法是,它会选择一些具有在其中媒体随机流派。一旦被选中,它就会在最高评分的媒体上进行排序,我认为要采用“顶级媒体”并在视图内使用它。

这是一个相当昂贵,丑陋的查询,我想要一些方法来优化它。

我可以将选择媒体转换为原始查询吗?

我应该从另一个方向接近这一点,并选择随机高评级的媒体,并从他们获取流派? (也可以接受,但如果它没有提供任何改进,那么他们没有意义)

我使用Rails 3,Ruby 1.9.2和MySQL与InnoDB。

+0

这将是有益的,如果你可以发表你的与此相关的查询表的精简下来的例子。另外,哪种模式是上述方法中的? – rjk 2011-05-26 02:21:55

+0

查看答案http://stackoverflow.com/questions/211329/quick-selection-of-a-random-row-from-a-large-table-in-mysql – 2011-05-26 02:55:23

+0

两张表。流派和媒体 媒体通过多对一来分属于流派。 – Samuel 2011-05-26 03:30:54

回答

1

我的解决方案

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

这工作像魔术一样。非常感谢! – Samuel 2011-05-27 08:49:02

+1

没问题。没有魔法,只有API。 :) – Anton 2011-05-27 09:48:29