ruby-on-rails - Rails 缓存数据库查询和最佳实践

标签 ruby-on-rails caching memcached

我网站上的数据库负载变得非常高,所以现在是我缓存常见查询的时候了,这些查询每小时被调用 1000 次,而结果没有改变。
因此,例如在我的城市模型上,我执行以下操作:

def self.fetch(id)   
  Rails.cache.fetch("city_#{id}") { City.find(id) }   
end 

def after_save
  Rails.cache.delete("city_#{self.id}")
end

def after_destroy
  Rails.cache.delete("city_#{self.id}")
end

所以现在当我第一次点击数据库时我可以 City.find(1) 但接下来的 1000 次我从内存中得到结果。伟大的。但是大多数对 city 的调用不是 City.find(1) 而是 @user.city.name ,其中 Rails 不使用 fetch 而是再次查询数据库......这是有道理的,但不完全是我想要它做的。

我可以做 City.find(@user.city_id) 但这很难看。

所以我想问你们。聪明的人在做什么?什么是
这样做的正确方法是什么?

最佳答案

关于缓存,有几个小点:

值得使用斜杠来分隔对象类型和 id,这是 Rails 约定。更好的是,ActiveRecord 模型提供了 cacke_key 实例方法,该方法将提供表名和 id、“cities/13”等的唯一标识符。

对 after_save 过滤器的一个小修正。由于您手头有数据,您不妨将其写回缓存,而不是将其删除。这为您节省了一次访问数据库的时间;)

def after_save
Rails.cache.write(cache_key,self)
结尾

至于问题的根源,如果你不断拉@user.city.name,有两个真正的选择:

  • 将用户的城市名称非规范化为用户行。 @user.city_name(保留 city_id 外键)。该值应在保存时写入。

  • -或者-
  • 实现你的 User.fetch 方法来急切加载城市。只有在城市行的内容永远不会改变(即名称等)时才这样做,否则你可能会打开一堆关于缓存失效的蠕虫。

  • 个人意见:
    实现基本的基于 id 的 fetch 方法(或使用插件)与 memcached 集成,并将城市名称非规范化为用户行。

    我个人不是缓存模型样式插件的忠实拥护者,我从未见过可以节省大量开发时间的插件,而且我还没有匆忙完成。

    如果您收到太多的数据库查询,那么绝对值得检查一下预先加载(通过 :include)(如果您还没有)。这应该是减少数据库查询数量的第一步。

    关于ruby-on-rails - Rails 缓存数据库查询和最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/344744/

    相关文章:

    html - CSS:只修改类中的一个元素

    ruby-on-rails - 如何确保多对多双方的关系是唯一的

    ios - AFNetworking 在应该接收 304 时返回 200 - ETag

    caching - Varnish 和 ESI : Fetching in parallel and possible workarounds

    java - 谷歌应用引擎 : Memcache or Static variable?

    ruby-on-rails - 更新模型新记录的方法

    javascript - 如何从 Ruby on Rails 应用程序将参数从根 html 元素传递到 ReactJS

    java - 咖啡因缓存: write() never get called

    caching - 如何在 Grails 1.2.5 上清除 Ivy 缓存

    ruby-on-rails-3 - 使Rails缓存中的特定模型无效