2017-03-26 216 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