2017-03-26 129 views
0

我有一个CSV文件,我用它来更新数据。更新不超过15000条记录需要很长时间(大约10分钟)。 这是我使用的代码:缓慢导入CSV到数据库中

task csv_updater_so: :environment do 
    require 'csv' 
    counter = 0 
    time = Benchmark.realtime do 
     save_folder = Rails.root.join('path_to_file') 
     CSV.foreach(save_folder, encoding:'iso-8859-1:utf-8', col_sep: ';', :quote_char => "\x00", headers: true) do |row| 
      #If the item is in the db I update its values 
      if item = Item.find_by_internal_code(row[4]) 
       item.update(:price => row[9], :stock_b => row[10]) 
      end 
      counter += 1 
      print "updated items => #{counter}" + "\r" 
     end 
    end 
end 

我觉得很奇怪,以更新从它只需一堆秒的xml文件相同的模型。难道我做错了什么?

我也曾尝试

task csv_updater_so: :environment do 
    require 'csv' 
    counter = 0 
    time = Benchmark.realtime do 
     save_folder = Rails.root.join('path_to_file') 
     updateable_items = CSV.foreach(save_folder, encoding:'iso-8859-1:utf-8', col_sep: ';', :quote_char => "\x00", headers: true).map do |row| 
      if item = Item.find_by_internal_code(row[4]) 
       item.update(:price => row[9], :stock_b => row[10]) 
      end 
      counter += 1 
      print "updated items => #{counter}" + "\r" 
     end 
     Item.import(updateable_items) 
    end 
end 
+0

您使用的是什么版本的Ruby和Rails?旧的CSV库确实非常慢。 (我问的是因为'Item.find_by_internal_code'是一种老式的查找方法。) – Raffael

+0

Ruby 2.3.3和Rails 4.2.6 耗时的部分似乎是更新方法,但即使我使用“touch”没有改进。 – Jack

+0

因此,如果删除更新行,脚本会在几秒钟内再次运行? – Raffael

回答

1

您的问题是,你正在做你基本上每个刀片做一个交易,所以这将是缓慢的自然的方式。

因此,为避免将CSV文件转换为SQL COPY命令,我的建议是使用activerecord-import gem。 它会照顾你的关联,并按照模型分组插入。另外,由于它为单独的gem中的数据库提供支持,因此可以利用数据库的一些很好的功能,如PostgreSQL中的数组。

+0

我发布的第二个代码是使用该宝石,但除非我以错误的方式使用它,否则时间不会低于10分钟 – Jack