处理大量的CSV文件

我会尝试扩展我的问题的标题。 我从事ruby项目。 我必须处理存储在CSV文件中的大量数据(大约120000)。 我必须阅读这些数据,处理并放入DB。 现在需要几天时间。 我必须加快速度。 问题是,有时在处理过程中我会遇到一些exception,我必须重复整个导入过程。 我认为更重要的是提高性能,而不是使用少量数据查找错误。 现在我坚持使用CSV文件。 我决定对处理脚本进行基准测试以找到瓶颈,并改进从CSV加载数据。 我看到以下步骤:

  1. 基准并修复最有问题的瓶颈
  2. 也许从CSV和处理拆分加载。 例如,在那里创建单独的表并加载数据。 在下一步中加载此数据,处理并放入右表。
  3. 引入线程以从CSV加载数据

现在我使用标准的ruby CSV库。 你推荐一些更好的gem吗?

如果你们中的一些人对类似的问题很熟悉,那么很高兴了解你的意见。

编辑:

数据库:postgrees

系统:linux

我没有机会亲自测试,但我明确地通过这篇文章,似乎做了这个工作。

https://infinum.co/the-capsized-eight/articles/how-to-efficiently-process-large-excel-files-using-ruby

您必须适应使用CSV而不是XLSX。 如果该站点将在此处停止代码,以供将来参考。 它的工作原理是在数据库中同时写入BATCH_IMPORT_SIZE记录,应该给予巨大的利润。

 class ExcelDataParser def initialize(file_path) @file_path = file_path @records = [] @counter = 1 end BATCH_IMPORT_SIZE = 1000 def call rows.each do |row| increment_counter records << build_new_record(row) import_records if reached_batch_import_size? || reached_end_of_file? end end private attr_reader :file_path, :records attr_accessor :counter def book @book ||= Creek::Book.new(file_path) end # in this example, we assume that the # content is in the first Excel sheet def rows @rows ||= book.sheets.first.rows end def increment_counter self.counter += 1 end def row_count @row_count ||= rows.count end def build_new_record(row) # only build a new record without saving it RecordModel.new(...) end def import_records # save multiple records using activerecord-import gem RecordModel.import(records) # clear records array records.clear end def reached_batch_import_size? (counter % BATCH_IMPORT_SIZE).zero? end def reached_end_of_file? counter == row_count end end 

https://infinum.co/the-capsized-eight/articles/how-to-efficiently-process-large-excel-files-using-ruby

有几种方法可以解决这个问题。 我个人会推荐SmarterCSV ,这使得使用arrays哈希处理CSV更快更容易。 如果可能的话,你肯定应该分开工作,也许是要处理文件队列并使用Redis批量完成

确保您的Ruby脚本可以处理作为参数给出的多个文件,即您可以像这样运行它:

 script.rb abc.csv def.csv xyz.csv 

然后使用GNU ParallelGNU Parallel以保持所有CPU内核的忙碌:

 find . -name \*.csv -print0 | parallel -0 -X script.rb 

-X将尽可能多的CSV文件传递给Ruby作业,而不会超出命令行的最大长度。 如果你希望GNU Parallel一次运行8个作业,你可以在parallel后添加-j 8 ,并且你可以使用--eta来获得估计的到达/结束时间:

  find . -name \*.csv -print0 | parallel -0 -X -j 8 --eta script.rb 

默认情况下, GNU Parallel将与CPU核心GNU Parallel运行多个作业。