【问题标题】:Rails/Active Record .save! efficiency questionRails/Active Record .save!效率问题
【发布时间】:2011-08-12 20:01:05
【问题描述】:

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

当我运行 each 时:

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

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

SELECT Fruit.* from Fruits where Fruit.ID = 5 LIMIT 1;
SELECT Color.* from Colors where Color.ID = 6 LIMIT 1;
SELECT TreeType.* from TreeTypes where TreeType.ID = 7 LIMIT 1;
INSERT into Apples (Fruit_id, color_id, treetype_id) 值 (6, 7, 8) RETURNING "id";

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

所以我想知道以下几点:

  • 这是典型的 ActiveRecord/Rails .save!方法,还是之前的开发者添加了某种自定义代码?
  • 为每个项目执行的这三个选择语句会导致显着的额外时间吗?
  • 如果它内置在 rails/active 记录中,是否可以轻松绕过它,如果这样可以使其更有效地运行?

【问题讨论】:

    标签: sql ruby-on-rails ruby activerecord


    【解决方案1】:

    您必须在保存时验证您的关联才能发生这种情况,如下所示:

    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 调用

    【讨论】:

      【解决方案2】:

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

      通常我不会期望 activerecord 进行不必要的查找——尽管这并不意味着它总是有效的......

      【讨论】:

      • 公平地说,ActiveRecord 只做你告诉它做的事情,即使有时你没有意识到你告诉它做什么。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-24
      • 2011-10-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多