我们有一些错误的数据,我正试图写一个data_migration来修复一些数据。有大约100万份错误记录。
什么是最好的方法来划分这些记录到组,这样我就不会锁定数据库的整个时间?假设我有这样一个查询:(错误的数据)
apples = Apple.where(seed: "rotten")
假设我想以5000个批次更新这些apples
。我该怎么做呢?
现在我有这样的东西…但这很奇怪。我怎么做第一个5000,然后下一个5000,直到没有更多的记录?为了复杂起见,我们假设有1,104,000条记录,现在有1,105,000条记录,用于一个漂亮的非整数。
这是我目前的解决方案:
class ChangeApples < ActiveRecord::Migration
def self.up
disable_ddl_transaction!
batch_separator = 20
apples = Apple.where(core:"rotten")
(0...batch_separator).each do |modulo|
batch = apples.where("id % #{batch_separator} = #{modulo}")
Rails.logger.info("Updating #{batch.count} apples with ids: #{batch.pluck(:id)}.")
batch.update_all(eventable_type: "Edible")
end
end
def self.down
raise ActiveRecord::IrreversibleMigration
end
end
一个选项可能是:
batch_separator = 5000
batches = 0
while Apple.where(core:"rotten").
limit(batch_separator).
update_all(eventable_type: "Edible") > 0 do
puts "Updating batch #{batches += 1}"
end
未测试的代码。
您还可以在循环中放置一个sleep和一个commit(如果不是自动发出的话)。就整体效率而言,它并不理想,但如果您不想让繁忙的OLTP数据库充斥着请求,那么它是一个不错的方法。