ruby-on-rails - Rails 中大量 CSV 导出的内存问题

标签 ruby-on-rails fastercsv

我正在尝试将大量数据从数据库导出到 csv 文件,但这需要很长时间,而且我担心我会遇到严重的内存问题。

有没有人知道在不增加内存的情况下导出 CSV 的更好方法?如果是这样,你能告诉我怎么做吗?谢谢。

这是我的 Controller :

def users_export
  File.new("users_export.csv", "w")           # creates new file to write to
  @todays_date = Time.now.strftime("%m-%d-%Y")
  @outfile = @todays_date + ".csv"

  @users = User.select('id, login, email, last_login, created_at, updated_at')

  FasterCSV.open("users_export.csv", "w+") do |csv|
    csv << [ @todays_date ]

    csv << [ "id","login","email","last_login", "created_at", "updated_at" ]
    @users.find_each do |u|
      csv << [ u.id, u.login, u.email, u.last_login, u.created_at, u.updated_at ]
    end
  end

  send_file "users_export.csv",
    :type => 'text/csv; charset=iso-8859-1; header=present',
    :disposition => "attachment; filename=#{@outfile}"
end

最佳答案

您正在构建一个巨大的字符串,因此您必须将整个 csv 文件保存在内存中。您还将加载所有用户,这些用户也将占用大量内存。如果您只有几百或几千个用户,这不会有任何区别,但在某些时候您可能需要做两件事

使用

User.find_each do |user|
  csv << [...]
end

这会分批加载用户(默认为 1000 个),而不是全部加载。

您还应该考虑将 csv 写入文件,而不是在内存中缓冲整个内容。假设您已经创建了一个临时文件,

FasterCSV.open('/path/to/file','w') do |csv|
  ...
end

会将您的 csv 写入文件。然后您可以使用 send_file 发送它。如果您已经打开了一个文件,FasterCSV.new(io) 也应该可以工作。

最后,在 Rails 3.1 及更高版本上,您可能可以在创建 csv 文件时对其进行流式传输,但这不是我之前尝试过的。

关于ruby-on-rails - Rails 中大量 CSV 导出的内存问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11221249/

相关文章:

ruby - FasterCSV 导入器到 DataMapper 模型 - 没有插入行

ruby-on-rails - 从复杂的 Rails 查询导出到 CSV

Ruby CSV,使用方括号作为行分隔符

ruby-on-rails - 将局部变量添加到 respond_to 渲染 View

ruby-on-rails - 使用 FasterCSV gem (MalformedCSVError) 解析 CSV 时出错

ruby-on-rails - 为 ActiveResource 添加记录器的最佳方式

ruby-on-rails - Rails 4 - 将日期时间转换为单独的日期和时间字段

ruby-on-rails - Rails Prawn文档的嵌入式字体错误

ruby-on-rails - Rails 模板 - 将索引添加到 :created_at using generate