有没有使用Rails导出超过10万条记录的CSV的优化方法?

时间:2019-05-16 12:56:59

标签: ruby-on-rails ruby

我的数据库中有20万个位置。所以我想将所有位置导出为CSV格式。这样做会花费太多时间下载。在Rails中优化代码的最佳方法是什么?

在控制器中:

 def index
    all_locations = Location.all
    respond_to do |format|
      format.csv { send_data all_locations.to_csv, filename: "locations-#{Date.today}.csv" }
    end
end

在模型中

def self.to_csv
    attributes = %w{id city address}

    CSV.generate(headers: true) do |csv|
      csv << ['Id', 'City', 'Address']

      all.each do |location|
        csv << attributes.map{ |attr| location.send(attr) }
      end
    end
end

2 个答案:

答案 0 :(得分:1)

我使用自己的数据对您的代码进行了一些调整。我进行了以下更改,并使用基准测试将结果提高了7倍。

您的型号:

def self.to_csv
  attributes = %w{id city address}

  CSV.generate(headers: true) do |csv|
    csv << ['Id', 'City', 'Address']
    all.pluck(attributes).each { |data| csv << data }
  end
end

使用pluck只会获得所需的数据,然后将所有数据推入csv数组中。

答案 1 :(得分:0)

如果您使用的是 Postgresql ,则可以在application_record.rb

中使用它
def self.to_csv_copy(attrs="*", header=[])
  rc = connection.raw_connection
  rv = header.empty? ? [] : ["#{header.join(',')}\n"]
  sql = self.all.select(attrs).to_sql
  rc.copy_data("copy (#{sql}) to stdout with csv") do
    # rubocop:disable AssignmentInCondition
    while line = rc.get_copy_data
      rv << line
    end
  end
  rv.join
end

然后做

Location.to_csv_copy(%w{id city address}, ['Id', 'City', 'Address'])

它甚至比上述解决方案还要快。