我想以优化的方式克隆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
对象的列表。也许我使用的方式已经过优化,但是我需要加快这一过程。这是我的代码
private def parallelFlatMapConcat[I, O](parallelism: Int)(sourceCreator: I => Source[O, NotUsed]) = {
val mapConcat = Flow[I].flatMapConcat(sourceCreator)
GraphDSL.create() { implicit builder =>
import GraphDSL.Implicits._
val balance = builder.add(Balance[I](parallelism))
val merge = builder.add(Merge[O](parallelism))
for (i ← 0 until parallelism)
balance.out(i) ~> mapConcat ~> merge.in(i)
FlowShape(balance.in, merge.out)
}
}
也许有更好的方法一次复制记录列表,然后用一个查询更新所有记录。我尝试使用Google进行搜索,但到目前为止还没有运气。
答案 0 :(得分:0)
如果您想尽快执行此操作,则可以使用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中工作。
如果您有任何rails magic列(created_at,updated_at等),则必须在SQL中手动添加。
答案 1 :(得分:0)
如果我理解正确,您想复制满足条件的对象
(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>
答案 2 :(得分:0)
短答案是使用single insert statement
,而不是multiple inserts
,即使如果它在一个DB transaction
。
和here创业板将帮助你做到这一点。 (感谢bulk_insert)