使用gem' postgres-copy'导入csv文件

时间:2016-09-05 04:52:04

标签: ruby-on-rails postgresql csv

目前,我想从CSV文件中将55,000条以上的记录导入我的数据库。这是我正在使用的代码:

CSV.foreach(Rails.root.join('db/seeds/locations.csv'), headers: true) do |row|
  val                = Location.find_or_initialize_by(code: row[0])
  val.name           = row[1]
  val.ecc            = row[2] || 'MISSING'
  val.created_by     = User.find_by(name: 'anh')
  val.updated_by     = User.find_by(name: 'anh')
  val.save!
end

然而,它太慢了,我刚刚安装了宝石&postffres-copy'。我阅读了官方文档,我相信我可以使用类方法copy_from来完成这项工作,但是如果你读了我当前的代码,你可以看到我将数据引用到另一个表(关联),并且文档没有提及关于关联或验证的任何内容。因此,我想知道是否有任何方法可以解决它。这是我第一次使用这个宝石。谢谢你的阅读。

2 个答案:

答案 0 :(得分:0)

我不知道那个gem,但如果它可以支持多表复制,我会非常惊讶,因为PostgreSQL的COPY可以在单个表上运行。 50K行并不是那么多。您可以尝试在事务中包装插入,以避免每个事务一次提交。怀疑你想要在交易中包装所有50K,但是这样的事情:

User.connection.begin_transaction
i = 0
CSV.foreach(...) do |row|
  ... # your original code here 

  i += 1
  if i % 500 == 0
    User.connection.commit_transaction
    User.connection.begin_transaction  
  end
end
User.connection.commit_transaction

这将一次插入500行记录,您应该会看到明显的加速。玩500的价值找到最佳点。

答案 1 :(得分:0)

所以,现在我明白我无法利用POSTGRESQL中的COPY命令,因为它无法复制多个表。因此,我切换到gem activerecord-import。与Philip Hallstrom上面提到的方法相比,使用activerecord-import可以获得更快的结果,1m20s vs 1m54s可以导入超过8000条记录。 这是安装gem activerecord-import后的代码。希望它可以帮助其他人。

locations = []
columns = [:code, :name, :ecc]
CSV.foreach(Rails.root.join('db/seeds/locations.csv'), headers: true) do |row|
  val                = Location.find_or_initialize_by(code: row[0])
  val.name           = row[1]
  val.ecc            = row[2] || 'MISSING'
  val.created_by     = User.find_by(name: 'anh')
  val.updated_by     = User.find_by(name: 'anh')
  locations << val
end
Location.import columns, locations, validate: false