find_each in rails with a has_many association



我正在尝试理解用于批量检索记录的Active Record find_each方法。

如果一篇帖子有很多评论(数千条评论),而我想呈现每条评论,我可以这样做:

@post.comments.each{| comment |…}

但如果我这样做,它会更快吗:

@post.comments.find_each{| comment |…}?

第二个查询有效吗?

我看到的是,通过在find_each之前执行@post.comments,已经获得了每条帖子的所有评论,所以用find_each结束查询可能是多余的?!

这是rails应用程序视图文件夹中的完整代码块:

json.comments @post.comments.find_each do |comment|
json.rating comment.rating
json.content comment.content
end

谢谢

@post.comments.find_each正确。当您调用@post.comments时,它创建的查询不会立即执行。这就是为什么您可以将其他查询方法(如whereorder等)链接到此关联。(为了可读性,sql日志被截断)

>> comments = Post.first.comments; nil;
Post Load (0.8ms)
=> nil
# NOTE: ^ no comments are loaded yet, until we need to output the result 
>> comments
Comment Load (2.0ms)
=> [#<Comment:0x00007f2ef1733328 id: 1, post_id: 1>, ...]  # <= array of 2000 comments

each方法被链接时,所有的注释都会加载到内存中,当您有数千条记录时,这是一个问题。

>> Post.first.comments.each{|c| print "." }
Post Load (0.6ms) 
# NOTE: executes one query for comments
Comment Load (1.4ms)
.................................................. # <= 2000 dots
=> [#<Comment:0x00007f2ef1560be0 id: 1, post_id: 1>, ...]

find_each方法被链接时,默认以1000为一批检索注释:

>> Post.first.comments.find_each{|c| print "." }
Post Load (0.6ms)
# NOTE: executes query to get 1000 comments at a time 
Comment Load (0.8ms)
.................................................. # <= 1000 dots
Comment Load (0.8ms)
.................................................. # <= 1000 dots
Comment Load (0.4ms)
# no more comments
=> nil

您也可以指定:batch_size:

>> Post.first.comments.find_each(batch_size: 100){|c| print "." }
Post Load (0.7ms)
# NOTE: get comments in batches of 100
Comment Load (0.6ms)
.................................................. # <= 100 dots
Comment Load (0.5ms)
.................................................. # <= 100 dots
# 21 queries in total
=> nil

https://api.rubyonrails.org/classes/ActiveRecord/Batches.html#method-i-find_each

最新更新