我网站上的数据库负载变得非常高,所以现在是时候缓存常见查询,这些查询每小时调用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.find(1),而是@ user.city.name,其中Rails不使用fetch但是再次查询DB ...这有意义但不完全是我想要它做的.
我可以做City.find(@ user.city_id),但这很难看.
所以我向你们提问.聪明人在做什么?这样做的正确方法是什么?
关于缓存,有几个小问题:
值得使用斜杠来分隔对象类型和id,这是rails惯例.更好的是,ActiveRecord模型提供了cacke_key实例方法,该方法将提供表名和id的唯一标识符,"cities/13"等.
对after_save过滤器进行一次小修正.由于您手头有数据,因此您可以将其写回缓存而不是删除它.这样可以省去一次数据库;)
def after_save Rails.cache.write(cache_key,self) end
至于问题的根源,如果你不断拉@ user.city.name,有两个真正的选择:
将用户的城市名称反规范化为用户行.@ user.city_name(保留city_id外键).应该在保存时写入该值.
-要么-
实施您的User.fetch方法以急切加载城市.只有在城市行的内容永远不会改变(即名称等)时才这样做,否则你可能会在缓存失效方面打开一堆蠕虫.
个人观点:实现基于id的基本fetch方法(或使用插件)与memcached集成,并将城市名称反规范化为用户的行.
我个人并不是缓存模型风格插件的忠实粉丝,我从来没有见过一个节省了大量开发时间的东西,我还没有匆忙成长.
如果您的数据库查询过多,那么如果您还没有,那么绝对值得检查出急切加载(通过:include).这应该是减少数据库查询数量的第一步.