问题描述
我有以下任务:
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
结束
此作业是将数据从用户标头表复制到设备信息子表中。它在生产数据库上运行,因此,迷你批处理可以防止锁定。它有一些问题。
- 它神秘地删除记录,无需复制所有必需的数据即可完成记录。不知道为什么。
- 这很慢。它正在运行约200万条记录,并且需要一个多小时,我需要加快速度。
- 它必须是幂等的。
我怎么
- 确保它仅在尚未迁移的记录上运行
- 合理地加快速度(增加批量大小,或者对迷你批次使用极限/偏移量以外的其他方式)
- 验证已成功完成
解决方法
问题是我不需要sql子句中的偏移量,因为左联接已经过滤掉了新记录。消除偏移会加快并修复作业。
将sql输出保存到变量并打印puts result.cmd_status
有助于验证每个批处理是否成功完成。