在rails应用程序中读取大型csv文件会占用大量内存 – 减少内存消耗的策略?

我有一个rails应用程序,允许用户上传csv文件,并在delayed_job gem的帮助下安排读取多个csv文件。 问题是应用程序将其文件中的每个文件读入内存,然后写入数据库。 如果只读取其中的1个文件,但是当读取多个文件时,服务器上的RAM会变满并导致应用程序挂起。

我试图找到解决这个问题的方法。

我研究的一个解决方案是将csv文件分成更小的部分并将它们保存在服务器上,然后读取较小的文件。 看到这个链接

example: split -b 40k myfile segment 

不是我的首选解决方案 有没有其他方法来解决这个问题,我没有必要打破文件。 解决方案必须是ruby代码。

谢谢,

您可以使用CSV.foreach只读取CSV文件的块:

  path = Rails.root.join('data/uploads/.../upload.csv') # or, whatever CSV.foreach(path) do |row| # process row[i] here end 

如果它在后台作业中运行,您还可以每n行调用GC.start


这个怎么运作

CSV.foreach在IO流上运行,如下所示:

 def IO.foreach(path, options = Hash.new, &block) # ... open(path, options) do |csv| csv.each(&block) end end 

csv.each部分是对IO#each的调用,它逐行读取文件( rb_io_getline_1 )并将读取的行rb_io_getline_1为垃圾回收:

 static VALUE rb_io_each_line(int argc, VALUE *argv, VALUE io) { // ... while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) { rb_yield(str); } // ... }