Ruby on Rails:Model.all.each vs find_by_sql(“SELECT * FROM model”)。每个?

时间:2010-03-30 02:23:27

标签: ruby-on-rails ruby activerecord

我对RoR很新。在我的控制器中,我正在迭代数据库中的每个元组。对于每个表,我曾经调用的每一列

SomeOtherModel.find_by_sql("SELECT column FROM model").each {|x| #etc }

工作得很好。当我后来改为

Model.all(:select => "column").each {|x| #etc }

循环以大致相同的速度开始,但很快变慢到比find_by_sql命令慢100倍的速度。这些电话应该是相同的,所以我真的不知道发生了什么。

我知道这些调用不是最有效的,但这只是一个中间步骤,一旦这种方法正常工作,我会更优化它。

所以澄清一下:为什么世界上调用Model.all.each的速度比使用find_by_sql.each慢得多?

谢谢!

2 个答案:

答案 0 :(得分:7)

两个调用都会进行相同的SQL调用,因此它们的速度大致相同。 Model.all确实经历了额外的间接层次。我认为all中的Rails从数据库连接中收集所有行,然后将该集合作为参数调用到另一个循环该集合并创建模型对象的方法。在find_by_sql中,它在1方法中完成所有操作。也许这会快一点。您的数据集有多大?如果该集合超过100个记录,则不应使用全部,而是使用find_in_batches。它使用限制和偏移来批量运行代码,而不是一次将整个表加载到内存中。您确实需要在select中包含主键,因为它使用它来执行顺序和限制。例如:

Model.find_in_batches(:batch_size => 100) do |group|
  group.each {|item| item.do_something_interesting }
end

答案 1 :(得分:2)

ScottD是正确的。 find_by_sql调用不会创建您看到B_的减速。速度问题是由于Model.all为获取的每个记录将模型实例加载到内存中。这可能会导致完全失败并且结果集足够大。仅供参考,这里的Rails指南非常清楚:http://guides.rubyonrails.org/active_record_querying.html#retrieving-multiple-objects