像User.find(:all).each这样的代码有什么问题?

时间:2009-05-06 22:56:31

标签: ruby-on-rails ruby

我刚刚在工作清单上阅读了这个要求:

  

意识到代码的陷阱,例如:User.find(:all).each

我立刻就知道我的工作不合格,因为对于我的生活,我不明白问题是什么。是吗......

  • 设计相关?我应该将数据库请求存储在变量中,然后然后迭代它吗?
  • 危险?
  • 太罗嗦了?我应该使用User.all.each吗? (-1字!w00t!)
  • 措辞简陋?它应该以“用户表恰好有300万行”开头吗?

5 个答案:

答案 0 :(得分:7)

我认为他们所寻找的“陷阱”是当有人写User.all.each时,它通常看起来像这样:

User.all.each do |u|
    next if !u.is_active
    ...
end

意味着在从DB加载了每个对象的全部内容之后,在过滤发生在过滤时,通过在查询中表达所需的属性,可以更有效地完成过滤。

答案 1 :(得分:5)

执行User.all将加载所有用户记录。如果你有300万条记录,它将加载所有300万个对象。这就是为什么这是一个坏主意。最好使用分页或条件等方法过滤SQL,以返回“完成工作”所需的最小子集

答案 2 :(得分:2)

  

这是罗嗦吗?你可以用User.all.each做同样的事情吗? (-1字!w00t!)

我们非常欣赏红宝石般的简洁。我一方面投票赞成实施Model.each,现在你让我考虑了它。

  

措辞简单吗?它应该以“用户表恰好有300万行”为前缀

我相信这是最合理的答案。您可能正在将大量记录加载到内存中。

我认为问题不在于用户表发生有3m记录,但它可能会在合理的时间范围内出现。

答案 3 :(得分:1)

这是一个陷阱,我不是母语为英语的人,但我的理解是,这不是一个直接的缺点,但它应该是你应该警惕的一个漏洞。这样做是未来的证明:

User.find_in_batches do |group|
  group.each do |user|
    user.do_something
  end
end

即使你一周内从一个用户增长到1000万个。

答案 4 :(得分:0)

好吧,如果你想听起来很聪明,你回答的是:这个问题没有陷阱,假设你想要修改或显示每个用户对象的值。 : - )