2012-03-28 12 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 %> 

私が達成しようとしているのは、ページ上の一連の点です。アンカータグのクラスがdoneの場合、緑で表示され、そうでない場合は赤で表示されます(CSSで行われます)。

ここで明らかになったDRYの問題とは別に、このクエリは非常に重いので、改善する方法を検討しています。

アウトレットは少なくとも1日1回監視されます(アウトレットhas_many:モニタ)。各コンセントについて、その特定の日に監視されているかどうかを確認し、それに応じてHTMLを出力する必要があります。

誰かが私にこれを助けることができたら、それは素晴らしいでしょう。 (これをキャッシュするためのアドバイスもあります)

前もって乾杯。

答えて

1

現在のモニタに対して調整済みの関連付けを行い、次に、インクルードを使用して、元のクエリで関連する現在のモニタリングをフェッチできます。 Postgresのレベルでは

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 

は、おそらくの#includeによって暗黙外部結合をサポートするためのmonitoringsのインデックス(outlet_id、のcreated_at)の恩恵を受けます。

ところで、ビューでデータベースクエリを実行するのは悪いスタイルです。ドメインロジックをモデルに入れ、コントローラにクエリを実行させ、結果をプレゼンテーションレイヤに渡します。

+0

これは実際には高価なクエリではないので、実際の問題を実証するまでキャッシングを心配しないでください。 – dbenhur

+0

私はこのソリューションが最も好きです。キャッシングに関しては、これは間違いなく必要だと思います。同じページに最大2000の店舗があり、5分ごとに爽やかです。これをキャッシュする最良の方法として何をお勧めしますか? – Ammar

+0

1つの外部結合で2000行をフェッチするのは高価な操作ではありません。まずそれを実装してから測定します。私はあなたがそれを必要としないので、キャッシュを推薦するつもりはありません。 – dbenhur

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というフィールドを追加できます。モニターが保存されるときはいつでも、適切なアウトレットモデルを日付で更新してください。次に、Monitorsをまったく照会する必要はありません。

また、そのページフラグメントをキャッシュすることを検討し、毎日有効期限切れにすることもできます。