0

基本的にテレビ番組のソーシャルネットワークであるアプリ(Rails 3)があります。そのため、ユーザーは相互に対話したり、tv_shows と対話したりできます。

users/tv_shows プロファイル ページを表示するたびにデータベース (mysql) に問い合わせるのを避けるための最善の戦略は何でしょうか?

例: テレビ番組のプロフィール ページ内で、シーズン、エピソード、俳優などの多くの情報を読み込む必要があります。これを行うには、複数のテーブルに参加する必要があり、毎日遅くなります。

私が最初に考えたのは、テレビ番組とストレージに関するすべての情報を 1 つのテーブルにまとめることでした。そのため、毎回これらの結合を行う必要はありません。

確かにパフォーマンスは向上しますが、最高ではありません。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 に答える