批量插入记录到活动记录表(Bulk Insert records into Active Recor

2019-07-21 06:47发布

我发现我的Model.create! 声明服用很长一段时间,当我在一次加入了大量的记录运行。 看着ActiveRecord的进口 ,但它并没有与散列数组的工作(这是我和我认为这是很常见的)。 我怎样才能提高性能?

Answer 1:

使用ActiveRecord的进口宝石。 让我们假设你正在阅读的CSV文件,并生成一个Product目录和要插入记录的1000批次:

batch,batch_size = [], 1_000 
CSV.foreach("/data/new_products.csv", :headers => true) do |row|
  batch << Product.new(row)

  if batch.size >= batch_size
    Product.import batch
    batch = []
  end
end
Product.import batch


Answer 2:

感谢Chris希尔德@cheald为他的2009年的文章 ,以显示我去的最好办法是多行插入命令。

下面的代码添加到我的initializers/active_record.rb文件,改变了我的Model.create!(...)调用Model.import!(...)远离它去。 一对夫妇的注意事项:

1)它不验证数据。
2)它使用SQL INSERT命令读取等的形式...

INSERT INTO <table> (field-1, field-2, ...) 
       VALUES (value-1-1, value-1-2, ...), (value-2-1, value-2-2, ...), ...`

...这可能不是所有的数据库正确的语法,但它与Postgres的工作。 它不会是很难改变的代码为您的SQL版本的相应的语法。

在我的具体情况,将19K +记录到一个简单的表,我的机器(的MacBook Pro配备8GB内存,2.4GHz的英特尔酷睿i5和和SSD)上使用从223秒去“model.create!” 7.2秒内使用了“model.import!”。

class ActiveRecord::Base

  def self.import!(record_list)
    raise ArgumentError "record_list not an Array of Hashes" unless record_list.is_a?(Array) && record_list.all? {|rec| rec.is_a? Hash }
    key_list, value_list = convert_record_list(record_list)        
    sql = "INSERT INTO #{self.table_name} (#{key_list.join(", ")}) VALUES #{value_list.map {|rec| "(#{rec.join(", ")})" }.join(" ,")}"
    self.connection.insert_sql(sql)
  end

  def self.convert_record_list(record_list)
    key_list = record_list.map(&:keys).flatten.uniq.sort

    value_list = record_list.map do |rec|
      list = []
      key_list.each {|key| list <<  ActiveRecord::Base.connection.quote(rec[key]) }
      list
    end

    return [key_list, value_list]
  end
end


Answer 3:

我开始跑步与大量的记录(> 10000)的问题,所以我修改了代码,同时在1000个记录组的工作。 这里是新代码的链接:

https://gist.github.com/jackrg/76ade1724bd816292e4e



Answer 4:

您还可以使用ActiveRecord的-insert_many宝石。 只是让对象的数组!

events = [{name: "Movie Night, time: "10:00"}, {name: "Tutoring", time: "7:00"}, ...]

Event.insert_many(events)


Answer 5:

使用事务加快了批量插入了很多!

Model.transaction do
    many.times{ Model.create! }
end

如果有多个型号都参与其中,做每一个模型,它影响了Model.transaction:

Model1.transaction do
    Model2.transaction do
        many.times do
            m1 = Model1.create!
            m1.add_model2
        end
    end
end


文章来源: Bulk Insert records into Active Record table