postgres中如何通过rake任务批量迁移数据?
How to migrate data in batches via rake task in postgres?
我有以下 rake 任务:
namespace :backfill do
desc "backfill device id data"
task device_ids: :environment do
user_count = User.where.not(device_id: nil).count
puts "Begin device_id backfill for #{user_count} users"
batch_size, offset = 2000, 0
begin
puts "Beginning backfill batch from rows #{offset} to #{offset + batch_size} out of #{user_count} rows"
ActiveRecord::Base.connection.execute <<-SQL
INSERT INTO user_device_infos (user_id, user_device_id, last_login_at, created_at, updated_at)
SELECT users.id, users.device_id, users.last_sign_in_at, current_timestamp, current_timestamp
FROM users
LEFT JOIN user_device_infos
ON users.id = user_device_infos.user_id
AND users.device_id = user_device_infos.user_device_id
WHERE users.device_id IS NOT NULL
AND user_device_infos.user_id IS NULL
ORDER BY users.created_at DESC
LIMIT #{batch_size}
OFFSET #{offset}
SQL
offset += batch_size
end until offset > user_count
puts "backfill complete"
end
结束
此作业正在将来自用户 header table 的数据复制到设备信息子 table 中。它在生产数据库上是 运行,因此是 mini-batches 以防止锁定。它有一些问题。
- 它神秘地删除了记录,没有复制所有需要的数据就完成了。不知道为什么。
- 速度很慢。 运行 大约有 200 万条记录,需要一个多小时,我需要加快速度。
- 需要幂等
我怎么能
- 确保它 运行 仅在尚未迁移的记录上
- 合理地加快速度(增加批量大小,或者为 mini-batches 使用 limit/offset 以外的东西)
- 验证它是否已成功完成
问题是我不需要 sql 子句中的偏移量,因为左连接已经过滤掉了新记录。删除偏移既加快了工作速度又修复了工作。
将 sql 输出保存到变量并打印 puts result.cmd_status
有助于验证每个批次是否已成功完成。
我有以下 rake 任务:
namespace :backfill do
desc "backfill device id data"
task device_ids: :environment do
user_count = User.where.not(device_id: nil).count
puts "Begin device_id backfill for #{user_count} users"
batch_size, offset = 2000, 0
begin
puts "Beginning backfill batch from rows #{offset} to #{offset + batch_size} out of #{user_count} rows"
ActiveRecord::Base.connection.execute <<-SQL
INSERT INTO user_device_infos (user_id, user_device_id, last_login_at, created_at, updated_at)
SELECT users.id, users.device_id, users.last_sign_in_at, current_timestamp, current_timestamp
FROM users
LEFT JOIN user_device_infos
ON users.id = user_device_infos.user_id
AND users.device_id = user_device_infos.user_device_id
WHERE users.device_id IS NOT NULL
AND user_device_infos.user_id IS NULL
ORDER BY users.created_at DESC
LIMIT #{batch_size}
OFFSET #{offset}
SQL
offset += batch_size
end until offset > user_count
puts "backfill complete"
end
结束
此作业正在将来自用户 header table 的数据复制到设备信息子 table 中。它在生产数据库上是 运行,因此是 mini-batches 以防止锁定。它有一些问题。
- 它神秘地删除了记录,没有复制所有需要的数据就完成了。不知道为什么。
- 速度很慢。 运行 大约有 200 万条记录,需要一个多小时,我需要加快速度。
- 需要幂等
我怎么能
- 确保它 运行 仅在尚未迁移的记录上
- 合理地加快速度(增加批量大小,或者为 mini-batches 使用 limit/offset 以外的东西)
- 验证它是否已成功完成
问题是我不需要 sql 子句中的偏移量,因为左连接已经过滤掉了新记录。删除偏移既加快了工作速度又修复了工作。
将 sql 输出保存到变量并打印 puts result.cmd_status
有助于验证每个批次是否已成功完成。