2011-05-26 69 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