在事务内部,ActiveRecord是否批量执行插入/删除操作?

时间:2011-05-07 17:11:40

标签: ruby-on-rails ruby-on-rails-3 activerecord transactions

我需要什么:

  1. 确保原子更新(没有记录可以处理2次)
  2. 批量删除所有选定的1000行

  3. @queue = Queue.where("col = 1").limit(1000)
    ids = []
    @queue.each do |row|
        Queue.do_something(row)
        ids << row.id
    end
    
    Queue.delete_all("id in (#{ids.join(',')}) ")
    

    是同样的

    Queue.transaction do
        @queue.each do |row|
            Queue.do_something(row)
            Queue.delete(row.id)
        end
    end
    

2 个答案:

答案 0 :(得分:16)

对于插入:

使用事务时,ActiveRecord不执行批量插入。但是它确实加快了速度,因为它使用单个事务来执行所有INSERT语句,而不是每个INSERT语句使用一个事务。

所以:

Queue.transaction do 
  @queue.each do |row|
    # an INSERT is done here
  end
end

会比以下更快:

@queue.each do |row|
  # an INSERT is done here
end

有关如何真正进行批量插入的详细信息,请查看此article

删除:

ActiveRecord delete_all调用是一个单独的SQL DELETE语句,所以我猜您可以将其视为批量删除(不需要在此使用事务,因为它已经被ActiveRecord封装在一个事务中)。在每条记录上调用delete时不会出现这种情况,这将导致多个SQL DELETE语句,从而启动和提交多个事务,并且整体性能降低。

答案 1 :(得分:3)

我建议你看一下ActiveRecord Import:https://github.com/zdennis/activerecord-import

我正在使用此工具插入10,000到100,000行数据。

books = []
10.times do |i| 
  books << Book.new(:name => "book #{i}")
end
Book.import books

如果您正在使用MySQL,它还支持ON DUPLICATE KEY UPDATE,因此您可以智能地插入新的/更新旧行。 https://github.com/zdennis/activerecord-import/wiki/MySQL:-On-Duplicate-Key-Update-Support