如何提高导出到CSV和XLS的速度

时间:2014-12-04 20:29:28

标签: ruby-on-rails ruby excel csv ruby-on-rails-4

我的Ruby模型有 export 方法

class InfoVoucher < ActiveRecord::Base
  include ActiveModel::Serializers::JSON

  default_scope { order('voucher_created_at DESC') }

  def attributes
    instance_values
  end

  def self.export(data, options = {})
    column_names = ["..","..","..","..",..]
    exported_col_names = ["Solicitud", "Inicio", "Final", "Duracion", "Pasajero", "Unidades", "Recargo", "Propina", "Costo", "Centro de costo", "Origen", "Destino",  "Proyecto", "Conductor", "Placas"]

    CSV.generate(options) do |csv|
      csv << exported_col_names

      data.each do |row_export|
        csv << row_export.attributes['attributes'].values_at(*column_names)
      end
    end
  end
end

这样可行,但是对于非常大的文件或查询,导出需要很长时间

起初我认为这是因为查询再次运行(一次用于HTML渲染,然后再次用于导出)但事实证明,避免再次运行查询以进行导出并没有提高速度 - How to reuse the query result for faster export to csv and xls without using global or session variable

在某些语言中,连接是一项非常昂贵的任务,特别是 csv 变量与导出的整个文件的内容连接,逐个记录

数据是在带有过滤器的where方法之后从ActiveRecord继承的模型的结果

@filters = {}
@filters['email_enterprise'] = session[:enterprise_email] ;

 # Add the selected filters
if (params[:f_passenger].to_s != '')
  @filters['id_passenger'] = params[:f_passenger] ;
end
if (session[:role] == 2)
  @filters['cost_center'] = session[:cc_name]
end

# Apply the filters and store them in the MemoryCache to make them available when exporting
@last_consult = InfoVoucher.where(@filters)

如何改善这一点以使其尽可能高效

1 个答案:

答案 0 :(得分:0)

保持记忆力低

使用庞大的数据集时,尝试尽可能少地创建对象,并根据需要从数据库中提取尽可能少的对象。您正在将info_vouchers表格中的每一列加载到InfoVoucher中的各个@last_consult类中。这是不必要的。

你可以做的一件事是@avlazarov建议的;使用#pluck直接从数据库进入 您感兴趣的列的嵌套数组。

useful_data = InfoVoucher.where(@filters).pluck(*column_names)

队列长时间运行任务

您应该始终对此类任务进行排队,以便稍后由工作人员处理。 Resquedelayed_job是受欢迎的选择。

这样做的好处是用户对导出的请求将是高效的,并立即通知他们他们的请求已排队。完成后将报告通过电子邮件发送给他们。