我有一个应用程序(rails 3),它基本上是一个电视节目的社交网络。这样用户就可以彼此互动以及与电视节目互动。
避免每次显示 users/tv_shows 个人资料页面时查询数据库 (mysql) 的最佳策略是什么?
例如:在电视节目简介页面中,我需要加载大量信息,例如季节、剧集、 Actor 等。为此,需要加入多个表,并且速度每天都在变慢。
我的第一个想法是将有关任何电视节目和存储的所有信息收集在一个表中,因此我不需要每次都进行这些连接。
当然我会有更好的表现,但不是最好的。我知道有很多替代方案,例如 memcache、redis 甚至 mongodb,但是解决这种情况的最佳方法是什么?
最佳答案
在我看来,最好的选择是为每个 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
关于mysql - Rails 中避免 mysql 查询的策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13072598/