1

关注.rb

belongs_to :show

def cached_show
  Rails.cache.fetch([self, :show]) do
    show      
  end
end

看法:

<% @recently_favorited.each do |following| %>
<li>
  <%= link_to "#{following.cached_show.name}", show_path(:permalink => following.cached_show.permalink) %> <span><%= "(#{pluralize(following.cached_show.followers, "follower")})" %></span>
</li>
<% end %>

控制台中的结果:

Cache read: followings/632770-20120929132253/show
Cache generate: followings/632770-20120929132253/show
  Show Load (0.7ms) SELECT `shows`.* FROM `shows`WHERE `shows`.`id` = 617 LIMIT 1
Cache write: followings/632770-20120929132253/show

Cache read: followings/632770-20120929132253/show
Cache fetch_hit: followings/632770-20120929132253/show

Cache read: followings/632770-20120929132253/show
Cache fetch_hit: followings/632770-20120929132253/show

问题:
这甚至是获取/缓存关联的“正确”实现吗?
那么性能呢?
在某些视图中(如示例中),它会在每个循环中命中缓存 3 次。在我的情况下,我在页脚中循环了 10 个项目,因此每个请求都会命中 30 次。这很好,还是每个循环一个 n+1 查询会更好?

建议和一般最佳实践表示赞赏:)

4

2 回答 2

2

据我所知,创建一种独特的方法来访问缓存与获取缓存并不常见。

大多数时候,您只需调用一个一直询问的方法cache,因为如果您在缓存键中包含一个对象,则该updated_at字段用于构建键。

对于您现在的示例,奇怪的部分是您实际上并没有对Following模型做任何事情,除了访问它的关联。因此,您应该直接在Show模型上查询:

@recently_favorited_shows = Show.joins(:followings).order("followings.created_at DESC").uniq

然后在你看来,循环播放节目。只有一个查询,没有n+1

如果您期望有数千次点击,我只是建议缓存结果@recently_favorited_shows并使其每 X 分钟过期:

@recently_favorited_shows = cache_store.fetch('recently_favorited_shows', expires_in: 5.minutes){Show.joins(:followings).order("followings.created_at DESC").uniq}

另一方面,如果您想在某个时间执行此操作,这里有一篇关于视图端缓存使用情况的很好的文章:http: //37signals.com/svn/posts/3113-how-key-based-cache-expiration-作品

无连接解决方​​案

编辑:现在,如果你在表中有无数行followings,这就是我要做的:

  • last_followed_at在表上创建一个字段shows,上面有一个索引
  • Following.rbbelongs_to :show, touch: :last_followed_at。这样,只要您在 中添加新条目Following,它就会更新shows表格上的字段
  • 然后,要获取最新关注的节目,请执行以下操作:

    @shows = Show.order("last_followed_at DESC").limit(10) # Fast query of course
    
于 2012-11-09T14:40:18.520 回答
0

这不能回答我的问题,但它解决了我的问题。我将这样做:

@shows = Rails.cache.fetch("recently_favorited_shows", expires_in: 1.minutes) do
  Show.find(Following.order("created_at DESC").limit(10).collect(&:show_id))
end

查询非常快(约 0.8 毫秒每个表示 IRB 控制台)

于 2012-11-10T14:48:52.777 回答