ActiveRecord在事务中执行批量插入/删除操作吗?

ActiveRecord在事务中执行批量插入/删除操作吗?

问题描述:

我需要什么:ActiveRecord在事务中执行批量插入/删除操作吗?

  1. 保证(无记录可被处理2次)
  2. 所有1000行批量删除所选

@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 

对于插入:

使用事务时,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语句,从而启动并提交多个事务并且整体上性能较低。

+0

在我的情况下,我需要删除记录,同时确保没有其他进程/实例将处理相同的记录。我使用mysql“FOR UPDATE”SQL子句来锁定选定的记录并使用ActiveRecord事务,因为我认为ActiveRecord会将这些删除作为单个批量删除sql执行或者更快地执行。 – newx 2011-05-07 18:24:31

+0

问题是我的电子邮件(在QUEUE上的记录)交付了两次 – newx 2011-05-07 18:25:14

+0

使用您的解决方案时,它确实获得了更快的速度......谢谢! :-) – 2012-09-15 10:16:03

我建议你看看ActiveRecord导入: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,它也支持对重复密钥更新,因此您可以智能地将新/更新旧行。 https://github.com/zdennis/activerecord-import/wiki/MySQL:-On-Duplicate-Key-Update-Support