Ruby on rails 极慢的csv导出

Ruby on rails 极慢的csv导出,ruby-on-rails,ruby,csv,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.ge

我们正在尝试生成一个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
def下载数据
开始日期,结束日期=获取开始日期
报告行=@report.report行。其中(“报告时间介于(?)和(?)之间”,开始日期,结束日期)
csv_string=csv.generate do|csv|
报告行。每个行都报告数据|
csv“#{Time.now}.csv”,:type=>“text/csv”)}
结束
结束

我会首先检查
报告时间
是否已编制索引,未编制索引的
报告时间
肯定会导致速度缓慢。有关添加索引的详细信息,请参阅

第二,您可以将结果缩减到您需要的范围,即不选择所有列,而只选择
时间
名称
、和

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
def下载数据
开始日期,结束日期=获取开始日期
报告行=@report.report行。其中(“报告时间在(?)和(?)之间)”,开始日期,结束日期。选择('time,name,value'))
csv_string=csv.generate do|csv|
report_lines.map{| row | csv“{Time.now}.csv”,type=>“text/csv”)}
结束
结束

我会首先检查
报告时间
是否已编制索引,未编制索引的
报告时间
肯定会导致速度缓慢。有关添加索引的详细信息,请参阅

第二,您可以将结果缩减到您需要的范围,即不选择所有列,而只选择
时间
名称
、和

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
def下载数据
开始日期,结束日期=获取开始日期
报告行=@report.report行。其中(“报告时间在(?)和(?)之间)”,开始日期,结束日期。选择('time,name,value'))
csv_string=csv.generate do|csv|
report_lines.map{| row | csv“{Time.now}.csv”,type=>“text/csv”)}
结束
结束

检查哪个部分花费了这么多时间

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

如果查询速度快,但Ruby速度慢,那么您可以尝试两种方法:

  • 或者尝试一些更快的CSV库(如
    最快的CSV
  • 在SQL中生成尽可能多的CSV。我的意思是:不是在那里创建
    ActiveRecord
    对象,而是为每一行获取连接的字符串。如果更好,但仍然太慢,您可以在数据库中只生成一个大字符串,然后为ust渲染它(此解决方案可能看起来不太好,而且看起来很难看,但在一个项目中我不得不使用它,因为它是最快的方法)

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

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

如果查询速度快,但Ruby速度慢,那么您可以尝试两种方法:

  • 或者尝试一些更快的CSV库(如
    最快的CSV
  • 在SQL中生成尽可能多的CSV。我的意思是:不是在那里创建
    ActiveRecord
    对象,而是为每一行获取连接的字符串。如果更好,但仍然太慢,您可以在数据库中只生成一个大字符串,然后为ust渲染它(此解决方案可能看起来不太好,而且看起来很难看,但在一个项目中我不得不使用它,因为它是最快的方法)

如果看不到
get\u start\u end\u date
report\u line
很难说是什么让代码变慢了。如果看不到
get\u start\u end\u date
report\u line
很难说是什么让代码变慢了。