Nic*_*rer 5 ruby activerecord ruby-on-rails activerecord-import
Rails版本: 4.2.7
Ruby版本: 2.3.3
我正在运行rake任务,将数百万个对象从CSV和JSON文件格式迁移到我的postgres数据库中.
我试图利用activerecord-import加速将对象写入数据库.
尽可能简化代码,前半部分处理对象类型1(来自一种数据类型),后半部分处理对象类型2.
第一个对象类型迭代如此(为问题简化):
importing_object_one_array = []
my_external_data.each do |element|
new_element = ObjectOne.new(
title: element[0],
body: element[1]
)
importing_object_one_array << new_element
end
ObjectOne.import importing_object_one_array, validate: false
Run Code Online (Sandbox Code Playgroud)
这个大约有250,000个对象运行,写的没有任何问题,我在控制台中进行了检查,并成功编写了对象.
但是,对象类型2具有相当多的额外对象,每个对象的大小和设计大致与对象类型1相同.
其中大约有4,040,000个.
我应该等多久ObjectTwo.import才能跑?我们现在已经好几个小时了.
或者,从调试的角度来看(因为我真的不想重新运行这个rake任务,除非我绝对不得不这样做),有什么脚本或策略可以看看当前是否ObjectTwo.import真的在运行(即使它正在运行)或者任务挂?
我检查了rails控制台,我们看起来仍然ObjectTwo和以前一样在数据库中.
我唯一的另一个想法是,因为我没有在运行之前打印到控制台#import(例如puts "Now starting import!"),我没有100%证明阵列中构建的对象已经完成.
由于很难提前猜测解决您的问题需要多少时间(这取决于数据库负载、索引和许多其他因素),因此我强烈建议您分批工作。
此外,这将使您的数据库面临一个非常大的请求,这可能会耗尽其 RAM、CPU 和网络资源。
所以,你可以做类似的事情:
total_records_count = large_query.count
large_query.find_in_batches(batch_size: 1000) do |batch|
puts("Progress: #{100*processed_records/total_records_count}%")
ObjectOne.import importing_object_one_array, validate: false
end
Run Code Online (Sandbox Code Playgroud)
total_records_count = guess_number_of_records_to_process
large_array.in_groups_of(1000) do |batch|
puts("Progress: #{100*processed_records/total_records_count}%")
ObjectOne.import importing_object_one_array, validate: false
end
Run Code Online (Sandbox Code Playgroud)
与解决方案 2 相比,优先使用解决方案 1,直接使用 ActiveRecord 和 find_in_batches,这将使用 OFFSET 和 LIMIT SQL 语句迭代数据,而不是将所有记录放入 RAM,然后导入它们。
如果您无法重新设计查询,则预计运行时间将非常线性,除非您的数据库资源远大于处理批处理所需的资源;否则,运行时间将是相当不可预测的。
| 归档时间: |
|
| 查看次数: |
210 次 |
| 最近记录: |