非常慢的csv导出

时间:2014-03-10 03:13:22

标签: ruby-on-rails ruby csv

我们正在尝试生成CSV文件供用户下载。但是,它非常慢,10k行CSV大约需要5分钟。

改善任何好主意?代码如下:

def download_data
  start_date, end_date = get_start_end_date
  report_lines = @report.report_lines.where("report_time between (?) and (?)", start_date, end_date)

  csv_string = CSV.generate do |csv|
    report_lines.each do |report_data|
      csv << [report_data.time, report_data.name, report_data.value]
    end
  end

  respond_to do |format|
    format.csv { send_data(csv_string, :filename => "#{Time.now}.csv", :type => "text/csv") }
  end
end

2 个答案:

答案 0 :(得分:3)

我首先要检查report_time是否已编入索引,未编入索引report_time肯定会导致缓慢。有关添加索引的详细信息,请参阅Active Record Migration

其次,您可以将结果减少到您需要的范围,即不选择所有列,而只选择timenamevalue

report_lines = @report.report_lines
                      .where("report_time between (?) and (?)", start_date, end_date)
                      .select('time, name, value')

尝试:

def download_data
  start_date, end_date = get_start_end_date
  report_lines = @report.report_lines.where("report_time between (?) and (?)", start_date, end_date).select('time, name, value')

  csv_string = CSV.generate do |csv|
    report_lines.map { |row| csv << row }
  end

  respond_to do |format|
    format.csv { send_data(csv_string, :filename => "#{Time.now}.csv", :type => "text/csv") }
  end
end

答案 1 :(得分:1)

检查哪个部分需要花费这么多时间。

如果是SQL查询,那么尝试优化它:检查你是否有索引,也许你需要强制另一个索引。

如果查询速度很快,但Ruby很慢,那么你可以尝试两件事:

  • 尝试更快的CSV lib(如fastest-csv
  • 在SQL中生成尽可能多的CSV。我的意思是:不是在那里创建ActiveRecord个对象,而是为每一行提取连接的字符串。如果它更好,但仍然太慢,你最终只能在数据库中生成一个大字符串并只为它呈现它(这个解决方案可能看起来不太好看,而且看起来很难看,但在一个项目中我不得不使用它,因为这是最快的方式)