Ruby / Rails - производительность по группам - PullRequest
2 голосов
/ 19 октября 2010

У меня есть коллекция Эпизодов , которая связана с Сезоном и Шоу .
Мне нужно отобразить их так:

Показать заголовок
.... Номер сезона 1
........ Название серии
........ Название серии
....Сезон № 2
........ Название серии
........ Название серии

Мой контроллер:

  def index
    @show_ids = Following.find_all_by_user_id(current_user.id).collect(&:show_id)
    @seen_ids = SeenEpisode.find_all_by_user_id(current_user.id).collect(&:episode_id)
    if @seen_ids.any?
      @episodes = Episode.find(:all, :conditions => ["show_id IN (?) AND episodes.id NOT IN (?)", @show_ids, @seen_ids], :joins => [:show, :season])
    else
      @episodes = Episode.find(:all, :conditions => ["show_id IN (?)", @show_ids], :joins => [:show, :season])
    end
  end

Мой взгляд:

<ul>
<% @episodes.group_by(&:show).each do |show, episodes| %>
  <li><h2><%= show.name %></h2></li>
  <% episodes.group_by(&:season).each do |season, episodes| %>
    <li><strong><%= season.number %></strong></li>
    <% episodes.each do |episode| %>
      <li><%= episode.name %></li>
    <% end %>
  <% end %>
<% end %>
</ul>

Это работает нормально, хотя я знаю, что это не очень хороший метод, и производительность SHIT (например, 10 секунд для 150 записей).Как получить такую ​​группу с хорошей производительностью?

Кроме того, как я могу ее изменить?

if @seen_ids.any?
  @episodes = Episode.find(:all, :conditions => ["show_id IN (?) AND episodes.id NOT IN (?)", @show_ids, @seen_ids], :joins => [:show, :season])
else
  @episodes = Episode.find(:all, :conditions => ["show_id IN (?)", @show_ids], :joins => [:show, :season])
end

Ответы [ 3 ]

4 голосов
/ 19 октября 2010

Во-первых, убедитесь, что в вашей базе данных есть индексы для любых столбцов внешнего ключа, с которыми вы запрашиваете (я обычно индексирую anything_id как само собой разумеющееся:

add_index :episodes,   :show_id
add_index :followings, :user_id

Комуочистите свои находки, попробуйте что-то вроде этого (из вашего обновленного сообщения):

@episodes = Episode.scoped(
              :conditions => ["show_id IN (?)", @show_ids],
              :include => :show )
if @seen_ids.present?
  @episodes = @episodes.scoped(
              :conditions => "seen_episodes.show_id IS NULL",
              :joins => :seen_episodes )
end

Выше предполагается, что вы используете Rails 2 (так как вы использовали синтаксис .find(:all) ...), но выможет исправить это, используя .where и т. д. вместо .scoped, если вы на Rails 3.

2 голосов
/ 19 октября 2010

с использованием предложения "NOT IN" обычно выполняется медленно.Вместо этого оставьте соединение в таблице SeenEpisode и добавьте условие, в котором SeenEpisode имеет значение NULL

Episode.find(:all, :joins => "LEFT JOIN SeenEpisode ON SeenEpisode.show_id = Episode.show_id", :conditions => "SeenEpisode.show_id IS NULL")

. Обратите внимание, что для ясности я пропустил некоторые пунктыДля этого нужно сохранить все записи из Episode и добавить в соответствующие столбцы из SeenEpisode.Затем условие удаляет эти совпадающие записи.

0 голосов
/ 19 октября 2010

Я заметил, что мой БД получил запрос Выберите * из шоу, где Id = 100 для каждой записи в цикле (show.name).Я предполагаю, что объединение не сработало из-за неоднозначных именованных столбцов (episodes.name и shows.name)

Это то, чем я закончил.

запрос:

@episodes = Episode.find(:all, :select => "episodes.*, shows.name AS show_name", :conditions => ["show_id IN (?) AND seen_episodes.episode_id IS NULL", @show_ids], :joins => "INNER JOIN shows ON shows.id = episodes.show_id LEFT JOIN seen_episodes ON seen_episodes.episode_id = episodes.id")

view:

<ul>
<% @episodes.group_by(&:show_name).each do |show_name, episodes| %>
  <li><h2><%= show_name %></h2></li>
  <% episodes.group_by(&:season_number).each do |season_number, episodes| %>
    <li><strong><%= season_number %></strong></li>
    <% episodes.each do |episode| %>
      <li><%= episode.name %></li>
    <% end %>
  <% end %>
<% end %>
</ul>

Кроме того, у меня уже был сезон_number в "столбце кэша" в каждом эпизоде.

Я думаю, что это нормально.Запрос не очень красивый, но, по крайней мере, мне нравится результат:

Завершено за 109 мс (просмотр: 31, DB: 15)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...