我应该允许activerecord-import运行多长时间?

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%证明阵列中构建的对象已经完成.

Ale*_*eau 0

由于很难提前猜测解决您的问题需要多少时间(这取决于数据库负载、索引和许多其他因素),因此我强烈建议您分批工作。

此外,这将使您的数据库面临一个非常大的请求,这可能会耗尽其 RAM、CPU 和网络资源。

所以,你可以做类似的事情:

如果 my_external_data 来自 activerecord 查询

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)

如果 my_external_data 是经典 ruby​​ 对象的列表

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,然后导入它们。

如果您无法重新设计查询,则预计运行时间将非常线性,除非您的数据库资源远大于处理批处理所需的资源;否则,运行时间将是相当不可预测的。