ruby-on-rails - 优化读取数据库和写入csv文件

标签 ruby-on-rails ruby csv sidekiq

我正在尝试从数据库中读取大量单元格(超过 100.000 个)并将它们写入 VPS Ubuntu 服务器上的 csv 文件。碰巧服务器没有足够的内存。

我正在考虑一次读取 5000 行并将它们写入文件,然后再读取 5000 行,等等。

我应该如何重构我当前的代码以使内存不会被完全消耗?

这是我的代码:

def write_rows(emails)

  File.open(file_path, "w+") do |f|
    f << "email,name,ip,created\n"
    emails.each do |l|
      f << [l.email, l.name, l.ip, l.created_at].join(",") + "\n"
    end
  end
end

该函数由 sidekiq worker 调用:

write_rows(user.emails)

感谢您的帮助!

最佳答案

这里的问题是,当您调用 emails.each 时,ActiveRecord 从数据库中加载所有记录并将它们保存在内存中,为避免这种情况,您可以使用方法 find_each :

require 'csv'

BATCH_SIZE = 5000

def write_rows(emails)
  CSV.open(file_path, 'w') do |csv|

    csv << %w{email name ip created}

    emails.find_each do |email|
      csv << [email.email, email.name, email.ip, email.created_at]
    end
  end
end

默认情况下,find_each 一次加载 1000 条记录,如果你想加载 5000 条记录,你必须将选项 :batch_size 传递给 find_each:

emails.find_each(:batch_size => 5000) do |email|
  ...

有关find_each 方法(以及相关的find_in_batches)的更多信息可以在Ruby on Rails Guides 上找到.

我使用 CSV 类来编写文件,而不是手动连接字段和行。这并不是性能优化,因为在文件上写入不应成为此处的瓶颈。

关于ruby-on-rails - 优化读取数据库和写入csv文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21160647/

相关文章:

ruby-on-rails - 无法使用Docker Compose将mongodb与Rails容器连接

visual-studio - 数据驱动的 MS 使用分号分隔符测试 CSV

javascript - CSV 太大,无法通过 AJAX 处理

c++ - 将字符串元素分配给结构数组中的结构

ruby-on-rails - Spork 和 minitest : testdrb exits with SystemExit exception

ruby-on-rails - `*` 用作参数时的含义(不像*arg,只是*)

ruby-on-rails - Rails - 基于另一个模型验证属性

ruby-on-rails - 将 Rails/ClearDB App 推送到 Heroku 错误 'Can' t 连接到 '127.0.0.1' 上的 MySQL 服务器

Ruby:计算唯一排列的数量而不使用 .permutation 和数据集中的重复项

ruby - 在 Ruby 中需要串行端口通信方面的帮助