【问题标题】:How to improve speed of export to CSV and XLS如何提高导出到 CSV 和 XLS 的速度
【发布时间】:2014-12-04 20:29:28
【问题描述】:

我有一个具有 export 方法的 Ruby 模型

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 变量正在与导出的整个文件的内容连接,逐条记录

data 是从 ActiveRecord 继承的带有过滤器的 where 方法的模型的结果

@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)

如何改进它以使其尽可能高效

【问题讨论】:

  • 尝试使用 pluck 检索属性而不是构建 AR 对象? apidock.com/rails/ActiveRecord/Calculations/pluck
  • @avlazarov 我从来没有听说过,我很新,它如何帮助我提高速度?我看到它允许过滤器和查询,但我需要导出的结果已经在 data 变量中过滤并准备好了
  • data 到底是什么?
  • @Deefour 我已经更新了问题以解释什么是数据
  • @avlazarov 我对 Ruby 很陌生。在哪一行代码中创建了一个新的 AR 对象?

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


【解决方案1】:

保持低内存

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

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

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

排队长时间运行的任务

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

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

【讨论】:

猜你喜欢
  • 2020-10-10
  • 1970-01-01
  • 1970-01-01
  • 2014-12-03
  • 2015-01-30
  • 2018-12-30
  • 2012-12-19
  • 1970-01-01
  • 2017-06-23
相关资源
最近更新 更多