Оптимизировать ActiveRecord Query - PullRequest
4 голосов
/ 26 мая 2011

Я работал над оптимизацией моего приложения на Rails, но застрял в одном конкретном запросе:

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.

1 Ответ

1 голос
/ 26 мая 2011

Мое решение

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...