我想克隆一个优化的方式ActiveRecord
对象的列表。也许,我使用的方式已经被优化,但我需要加快这一进程。所以这是我的代码
ActiveRecord::Base.transaction do
data = MyModel.where(column_1: 'x')
data.each do |item|
new_item = item.dup
new_item.column_2 = 'y'
new_item.save!
end
end
也许有一次,然后用一个查询更新所有这些重复的记录列表的一个更好的办法。我试图谷歌,但没有运气至今。
如果我的理解没错,你要复制符合条件的对象
(column_1: 'x')
你可以试试这个方法,看起来像它会做同样的
MyModel.where(column_1: 'x').find_each { |u| u.dup.update(column2: 'y') }
但慢一点(基准N = 1000)
<Benchmark::Tms:0x00007f96e6a1b970 @label="**dup.update**", @real=6.75463099999979, @cstime=0.0, @cutime=0.0, @stime=0.331546, @utime=2.2468139999999996, @total=2.5783599999999995>,
<Benchmark::Tms:0x00007f96e8cb23f8 @label="**dup.save!**", @real=6.470054999999775, @cstime=0.0, @cutime=0.0, @stime=0.32828900000000005, @utime=1.972385, @total=2.300674>
简短的回答是改为使用single insert statement
的multiple inserts
即使如果它在一个DB transaction
。
而bulk_insert宝石将帮助你做到这一点。 (感谢arieljuod)
如果你想尽快做,那么SQL是要走的路。
像这样的东西会做:
ActiveRecord::Base.connection.execute <<-SQL
INSERT INTO my_models (column_1, column_2, column_3, ..)
SELECT column_1, 'y', column_3, ..
FROM my_models WHERE column_1 = 'x';
SQL
这应该在PostgreSQL和MySQL工作。
如果您有任何轨道魔法列(created_at,等的updated_at),他们将不得不在SQL手动添加。