使用ActiveRecord

时间:2017-05-26 22:48:51

标签: sql ruby-on-rails postgresql activerecord sidekiq

我有一个包含3亿条目的数据集,我需要将它插入PostgreSQL数据库。数据采用亚马逊S3上的gzip压缩JSON行文件的形式。每个文件都有50k JSON行,每个JSON行大约35kb。

现在我正在Sidekiq为S3(~5500)上的每个JSON行文件创建一个作业。 我有Heroku(标准2x工人)处理这些文件的工作人员。工作人员下载JSON行文件,解析行并开始通过ActiveRecord将它们保存到数据库(一次执行1000个事务)。现在我发现每个工人每分钟可以坚持2500行。我还发现,如果我显着增加工作人员数量(例如50),每个工作人员每分钟插入的条目数量会下降(我的数据库应该能够处理多达200个连接)。

我希望我能更快地做到这一点。是否有提高性能的指针?

这是Sidekiq工作中的逻辑:

# entries is an array of 50k strings, where each string is a JSON object
entries = EntriesDataService.get_entries(s3_url)

entries.each_slice(1000) do |chunk|
 ActiveRecord::Base.transaction do
   chunk.each {|p| Model.from_json_string(p)}
 end
end

1 个答案:

答案 0 :(得分:2)

您可以为每个块执行多重插入:

entries.each_slice(1000) do |chunk|
  values = get_values_from_chunk(chunk)
  query = "INSERT INTO table (col1, col2, ...) VALUES #{values}"
  ActiveRecord::Base.connection.execute(query)
end

get_values_from_chunk方法必须以字符串形式返回一组值,例如:

values = "(col1v1, col2v1, ...), (col1v2, col2v2, ...), ..., (col1vn, col2vn, ...)"

通过这种方式,插入将得到极大改善。