Rails / Active Record .save!效率问题

时间:2011-08-12 20:01:05

标签: sql ruby-on-rails ruby activerecord

rails / ruby​​的新手(使用rails 3和ruby 1.9.2),我试图摆脱正在执行的一些不必要的查询。

当我在运行每个人时:

apples.to_a.each do |apple|
  new_apple = apple.clone
  new_apple.save!
end

我检查了sql LOG,我看到三个select语句后跟一个insert语句。 select语句似乎完全没必要。例如,它们就像:

SELECT Fruit。*来自Fruits,其中Fruit.ID = 5 LIMIT 1;
SELECT Color。* from Color其中Color.ID = 6 LIMIT 1;
从TreeTypes中选择TreeType。*,其中TreeType.ID = 7 LIMIT 1;
INSERT到Apples(Fruit_id,color_id,treetype_id)值(6,7,8)返回“id”;

看起来,这不会花费太多时间,但是当我有70k的插入物运行时,我打赌每个插入的三个选择将花费相当多的时间。

所以我想知道以下内容:

  • 这是典型的ActiveRecord / Rails .save!方法,还是以前的开发人员添加了某种自定义代码?
  • 对于每个项目执行的那三个选择语句是否会导致明显的额外时间?
  • 如果将其内置到rails / active record中,是否可以轻松绕过它,如果这样可以更有效地运行?

2 个答案:

答案 0 :(得分:3)

您必须在保存时验证您的关联,以便发生这样的事情:

class Apple < ActiveRecord::Base
  validates :fruit,
    :presence => true
end

为了验证关系,必须加载记录,并且这需要针对每个记录依次进行每个验证。这是save!

的标准行为

如果你想生活危险,你可以在没有验证的情况下保存:

apples.to_a.each do |apple|
  new_apple = apple.clone
  new_apple.save(:validate => false)
end

更好的方法是在RDBMS支持的情况下通过执行大量插入来直接在SQL中操作记录。例如,MySQL将允许您通过一次INSERT调用插入数千行。您通常可以通过使用Apple.connection访问层来执行此操作,该层允许您使用execute

之类的内容进行任意SQL调用

答案 1 :(得分:0)

我猜测有一个before_save编辑:(或上面建议的验证)方法正在查找水果的颜色和类型,并在保存水果时将其与其余属性一起存储 - 在这种情况下,这些查找是必要的......

通常我不希望activerecord进行不必要的查找 - 虽然这并不意味着它总是有效...

相关问题