gpt4 book ai didi

ruby-on-rails - 缓存有限的关联

转载 作者:行者123 更新时间:2023-12-04 18:49:00 26 4
gpt4 key购买 nike

我正在尝试使用其关联缓存 ActiveRecord。 问题是在访问检索到的记录上的关联时存在数据库查询。

通常情况下,我只是使用急切加载缓存 Rails.cache.write('post', Post.includes(:comments).find(99)) .这似乎有效,但问题是我只想缓存关联的有限子集,并且在急切加载时忽略限制(例如提到 here)。所以Post.includes(:popular_comments).find(99)将返回所有评论,而不仅仅是热门评论。

所以我尝试在延迟加载关联后缓存对象,但不幸的是在拉出对象时发生查询:

class Post < ActiveRecord::Base
has_many :comments
has_many :popular_comments, :class_name > 'Comment', :limit => 20, :order => :votes

post = Post.find(99)
post.popular_comments # lazy-load limited associations
Rails.cache.write('post', post)
...
Rails.cache.read('post').popular_comments # Unwanted SQL query :(

我试过缓存一个克隆,同样不需要的 SQL 查询。我已经尝试过使用 redis 和 memcached 实现,结果相同。奇怪的是,这个序列确实适用于控制台 afaict,但在 Controller 或 View 中的简单用法失败(即发生 SQL)。

更新(2017 年 4 月):我现在要说这是一个愚蠢的前提。缓存整个对象通常是浪费的,因为它使用大量缓存存储,并且序列化/反序列化它们很慢。缓存关联(如本问题中所问)也将浪费乘以 N。通常,仅缓存原始 ID 和 HTML 片段会更有效。

最佳答案

试试 post.popular_comments.reload
首先,在急切加载时实际上忽略了限制。来自 the docs :

If you eager load an association with a specified :limit option, it will be ignored, returning all the associated objects



这意味着,就像您发现的那样,您必须自己将关联强加到父对象中。在我的实验中, post.popular_comments没有用(这是有道理的,因为它返回一个代理对象),有趣的是 post.popular_comments.all 也没有用. post.popular_comments(true)然而,有诀窍。在该代码下面调用重新加载,只需执行 post.popular_comments.reload还将关联加载到父类中。

我不确定这两个哪个更正确, post.popular_comments(true)post.popular_comments.reload .两者似乎都有点脆弱,但第二个读起来更好,更清楚地表达了你的意图。

我验证了这两种方法:
  • 将有限关联存储在 memcache 中
  • 从缓存加载后没有触发 SQL 查询

  • 我存储帖子的脚本:
    require 'pp'
    Rails.cache.clear
    post = Post.first

    #post.popular_comments(true)
    post.popular_comments.reload

    Rails.logger.info "writing to cache"
    s = Rails.cache.write "post", post
    Rails.logger.info "writing to cache done"

    并检索:
    require 'pp'
    Rails.logger.info "reading from cache"
    post = Rails.cache.read "post"
    Rails.logger.info "reading from cache done"
    Rails.logger.info post.popular_comments.inspect

    如果我一个接一个地运行,我的日志显示:
      Post Load (0.5ms)  SELECT `posts`.* FROM `posts` LIMIT 1
    Comment Load (0.5ms) SELECT `comments`.* FROM `comments` WHERE `comments`.`post_id` = 1 ORDER BY votes LIMIT 20
    writing to cache
    writing to cache done
    reading from cache
    reading from cache done
    [#<Comment id: 1, ...

    MySQL 日志还确认第二个脚本不会触发关联查询。

    这是用 Rails 3.1.1 完成的

    关于ruby-on-rails - 缓存有限的关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9125727/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com