2012-03-28 61 views
0

背景:的Rails 3.2 - 查詢性能(Postgres的)

我創建一個儀表板作爲一個項目,我有一個查詢,我認爲將是一個很大的性能問題:

<% 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 %> 

我想要實現的是一頁上的一系列點。如果錨標記有一個完成的類,它將顯示爲綠色,如果不是,則它將顯示爲紅色(通過CSS完成)。

除了這裏明顯DRY問題,這個查詢是非常沉重的,所以我在尋找方法來改善它。

每天至少監視一次插座(插座has_many:監視器)。對於每個出口,我需要檢查它是否在該特定日期受到監控,並相應地輸出HTML。

如果有人能幫助我,這將是太棒了。 (另外,任何意見緩存這將不勝感激)。

提前歡呼:)。

回答

1

您可能會使電流監控條件的關聯,然後使用包括對原始查詢獲取相關的電流。監控。

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,created_at)支持外連接通過的#includes暗示受益。

順便說一句,這是不好的風格是在您的視圖執行數據庫查詢。將域邏輯放入模型中,讓您的控制器執行查詢並將結果提供給表示層。

+0

BTW,這應該不是實際上是貴得離譜的查詢,所以不用擔心緩存,直到你證明一個實際的問題 – dbenhur 2012-03-29 02:22:06

+0

我喜歡這個解決方案是最我想。在緩存方面,我認爲這絕對是需要的。同一頁面上可能會有多達2000個網點,每5分鐘左右刷新一次。你會推薦什麼作爲緩存這個最好的方法? – Ammar 2012-03-29 06:58:23

+0

使用一個外連接獲取2000行不是一個昂貴的操作。先實施然後測量。我不會推薦緩存,因爲我懷疑你需要它。 – dbenhur 2012-03-29 10:17:06

0

也許嘗試:

<% @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個大的查詢。

0

的一個好方法緩存這將與使用回調來反規範化數據庫。在您的Outlet模型中,您可以添加一個名爲last_monitored_on的字段;任何時候保存一臺顯示器,用日期更新合適的Outlet型號。然後,你根本不必查詢監視器。

你也可以考慮緩存該頁面片段,並讓它每天到期。