Rails中巨大的CSV导出导致内存问题

3 ruby-on-rails fastercsv

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

有没有人知道在没有内存累积的情况下导出CSV的更好方法?如果是的话,你能告诉我怎么样吗?谢谢.

这是我的控制器:

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
Run Code Online (Sandbox Code Playgroud)

Fre*_*ung 7

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

使用

User.find_each do |user|
  csv << [...]
end
Run Code Online (Sandbox Code Playgroud)

这会批量加载用户(默认为1000)而不是所有用户.

您还应该考虑将csv写入文件而不是缓存内存中的所有内容.假设您已创建临时文件,

FasterCSV.open('/path/to/file','w') do |csv|
  ...
end
Run Code Online (Sandbox Code Playgroud)

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

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