Ruby-on-Rails 3.2 : Export a CSV with a large data set (100, 000 条记录)

标签 ruby-on-rails csv scalability delayed-job ruby-on-rails-3.2

简介

我有一个应用程序有多个表,有些有关联,有些没有关联。

一些表需要容纳大约 100,000 个条目。

该应用程序在 Ruby 1.9 上使用 Rails 3.2,并托管在 Heroku 上。如果需要,我可以接触到 worker 。

问题中的要求

该应用程序的一个重要要求是允许用户将数据导出为 CSV - 一个要求是允许用户过滤他们想要导出的数据,但正如您将看到的那样,我目前并不担心这一点下面的数据,我对要导出的数据进行了硬编码,但这确实排除了创建 rake 任务以导出整个表的可能性。

此外,实现的方法必须考虑到允许被多个表使用以避免重复代码。

当前解决方案

我正在我的应用程序中实现 delay_job 并在作业中执行 CSV 生成。在执行此操作时,我遵循在 http://www.ayokasystems.com/blog/delegating-long-running-jobs-in-rails/ 上找到的解决方案。来自“阿卜杜拉”。

这个想法是以 CSV 格式生成数据并将其保存在 UserJobs 表中的 LONGTEXT 字段中,以允许用户在完成后下载。

问题

上述教程中使用的方法在我的应用程序中运行良好,直到我一次运行 100,000 条记录的作业。为了克服这个问题,我尝试将很酷的 find_each 函数添加到 perform 方法中,但延迟作业 worker 每次尝试处理它时都会报告一个错误:

[Worker(host:*** pid:18637)] ReportJob failed with NoMethodError: undefined method `each' for #<Title:0x007ff20c1ec1b0> - 0 failed attempts
[Worker(host:*** pid:18637)] ReportJob failed with NoMethodError: undefined method `each' for #<Title:0x007ff20ec47f18> - 1 failed attempts
[Worker(host:*** pid:18637)] 2 jobs processed at 10.5219 j/s, 2 failed ... 

我的执行方法代码是:
def perform
  Title.find_each do |titles|
    csv_data = CSV.generate do |csv|
      titles.each do |t|
        csv << t.to_csv
      end
    end
    user_job = UserJob.find(user_job_id)
    user_job.update_attribute :data, csv_data
  end
end

任何人都可以看到问题可能是什么,我想我刚刚在循环处理事情时犯了一个愚蠢的错误。

我非常愿意接受有关如何完成相关要求的任何其他建议,但请记住我对 Heroku 的限制。

最佳答案

您正在尝试对每个进行迭代,但在这种情况下,标题是标题(而不是数组)的实例。

csv_vals = []
columns = [:name, :release_date, :studio]

Title.find_each(:select => columns) do |title| 
  columns.each {|value| csv_vals << "#{title[value]}"}
end

# comma separated string 
csv_string = csv_vals.join(',')

有更优雅的方式来制定 CSV 字符串,但我懒得尝试。

重要的是您只在需要的列上执行 SELECT。对于 100 000 条记录,这增加了很多带宽较低的 DB 通信。只需使用 find_each,您就可以获得每一行的所有列,而您不需要它们。

关于Ruby-on-Rails 3.2 : Export a CSV with a large data set (100, 000 条记录),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10245613/

相关文章:

ruby-on-rails - redis blocking peek in ruby​​,换句话说,在不删除的情况下阻止pop

php - 需要将表格标题添加到导出的 CSV 文件中

mysql - 设置数据库分片 - 没有跨数据库查询

design-patterns - 如何限制针对 Azure 中的队列工作的每个作业/租户的辅助角色

ruby-on-rails - 我如何邀请用户(使用 devise_invitable)并在邀请过程中填充其他字段?

ruby-on-rails - 嵌套表格: link_to_add: customizing to work with multiple fields_for builders

ruby-on-rails - 如何获取视频的属性

Python:查找和替换批处理 csv 文件中的字符串

mysql - 如何从 Word 文档中提取数据到 MySQL 表中?

python - 如何在水平缩放的游戏服务器中管理元信息?