ActiveRecord在事务中执行批量插入/删除操作吗?
问题描述:
我需要什么:ActiveRecord在事务中执行批量插入/删除操作吗?
- 保证(无记录可被处理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语句,从而启动并提交多个事务并且整体上性能较低。
答
我建议你看看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
在我的情况下,我需要删除记录,同时确保没有其他进程/实例将处理相同的记录。我使用mysql“FOR UPDATE”SQL子句来锁定选定的记录并使用ActiveRecord事务,因为我认为ActiveRecord会将这些删除作为单个批量删除sql执行或者更快地执行。 – newx 2011-05-07 18:24:31
问题是我的电子邮件(在QUEUE上的记录)交付了两次 – newx 2011-05-07 18:25:14
使用您的解决方案时,它确实获得了更快的速度......谢谢! :-) – 2012-09-15 10:16:03