0

我有一个应用程序(rails 3),它基本上是一个用于电视节目的社交网络。因此,用户可以彼此互动并与 tv_shows 互动。

每次显示 users/tv_shows 个人资料页面时,避免查询数据库(mysql)的最佳策略是什么?

例如:在电视节目简介页面中,我需要加载很多信息,例如季节、剧集、演员等。为此,需要加入多个表格,并且每天都在变慢。

我的第一个想法是将有关任何电视节目和存储的所有信息收集在一张桌子上,所以我不需要每次都进行这些连接。

我肯定会有更好的表现,但不是最好的。我知道有很多替代品,比如 memcache、redis 甚至 mongodb,但这种情况下最好的方法是什么?

4

1 回答 1

1

在我看来,您最好的选择是为每个Show包含呈现页面所需的所有关系的预取数据的编组对象缓存。我使用 Redis 作为我的缓存,但您也可以使用 Memcache 或类似的东西。

shows = user.tv_shows.map do |show|
  if cached_show = $redis.get("shows:#{show.id}")
    # use the cached object
    Marshal.load(cached_show)
  else
    # cache has expired or was never created
    show.prefetch!
    # set the cache for the next visit and have it expire after +TIMEOUT+
    $redis.setnx("shows:#{show.id}", TIMEOUT, Marshal.dump(show))
    show
  end
end

在转储对象之前预取所有关系很重要,否则在解组缓存对象后会访问数据库。

下面是一个预取的例子:

class Show
  def prefetch!
    @actors ||= actors
    self
  end

  def actors
    @actors || 1.upto(10).map do |n|
      Actor.new(n)
    end
  end
end

class Actor
  def initialize(n)
    puts "initialize actor #{n}"
  end
end

show = Show.new.prefetch!
cache = Marshal.dump(show)
Marshal.load(cache).actors.length  # uses value stored in @actors

show2 = Show.new
cache2 = Marshal.dump(show2)
Marshal.load(cache2).actors.length  # calls database
于 2012-10-25T19:18:44.643 回答