Rails 3.2 - производительность запросов (Postgres) - PullRequest
0 голосов
/ 29 марта 2012

Справочная информация:

Я создаю панель мониторинга как проект, и у меня есть запрос, который, как мне кажется, будет иметь большое значение для производительности:

<% for outlet in @outlets %>
    <% if Monitoring.where(:outlet_id => outlet.id).where('date(created_at) = ?', Date.today).exists? %>
        <li>
            <a class="done" href="<%= outlet_url(outlet) %>" rel="tooltip" title="<%= outlet.name %>"></a>
        </li>
    <% else %>
        <li>
            <a href="<%= outlet_url(outlet) %>" rel="tooltip" title="<%= outlet.name %>"></a>
        </li>
    <% end %>
<% end %>

То, чего я пытаюсь достичь, - это серия точек на странице. Если у тега привязки есть класс done, он будет отображаться зеленым цветом, если нет, то будет красным (сделано через CSS).

Помимо очевидных проблем с СУХОЙ, этот запрос очень тяжелый, поэтому я ищу способы его улучшить.

Выход контролируется не реже одного раза в день ( Выход has_many: мониторы ). Для каждого выхода мне нужно проверить, отслеживался ли он в тот день, и вывести соответствующий HTML-код.

Если бы кто-нибудь мог мне помочь с этим, это было бы замечательно. (Кроме того, любые советы по кэшированию это будет оценено).

Заранее спасибо:).

Ответы [ 3 ]

1 голос
/ 29 марта 2012

Вы можете создать условную связь для текущих мониторов, а затем использовать include для извлечения связанных текущих мониторов в исходном запросе.

class Outlet
  has many :current_monitorings, :class_name => "Monitoring",
    :conditions => proc { [ 'monitorings.created_at > ?', Time.now.midnight ] }
end

@outlets = Outlet.includes(:current_monitorings)

@outlets.each do |outlet|
  if outlet.current_monitorings.empty?
    # the no monitor today case
  else
    # it's been monitored today
  end
end

На уровне Postgres вам, вероятно, будет полезен индекс мониторинга (outlet_id, creation_at) для поддержки внешнего объединения, подразумеваемого # include.

Кстати, это плохой стиль - выполнять запросы к базе данных по вашему мнению. Поместите доменную логику в свои модели, и пусть ваш контроллер выполнит запрос и предоставит результаты на уровень представления.

0 голосов
/ 29 марта 2012

Хороший способ кешировать это - денормализовать вашу базу данных с помощью обратных вызовов. В вашей модели Outlet вы можете добавить поле с именем last_monitored_on; при каждом сохранении монитора обновляйте соответствующую модель розетки с указанием даты. Тогда вам вообще не придется запрашивать мониторы.

Вы можете также рассмотреть возможность кэширования этого фрагмента страницы и позволить ему истекать ежедневно.

0 голосов
/ 29 марта 2012

Может быть попробовать:

<% @outlets.includes(:monitorings).each do |outlet| %>
  <% css_class = outlet.monitorings.any? { |m| m.created_at == Date.today } ? 'done' : '' %>
  <li><%= link_to '', outlet_url(outlet), :class => css_class, :rel => "tooltip", :title => outlet.name %></li>
<% end %>

Он выполнит 1 большой запрос.

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