如何通过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

结束

此作业是将数据从用户标头表复制到设备信息子表中。它在生产数据库上运行,因此,迷你批处理可以防止锁定。它有一些问题。

  1. 它神秘地删除记录,无需复制所有必需的数据即可完成记录。不知道为什么。
  2. 这很慢。它正在运行约200万条记录,并且需要一个多小时,我需要加快速度。
  3. 它必须是幂等的。

我怎么

  1. 确保它仅在尚未迁移的记录上运行
  2. 合理地加快速度(增加批量大小,或者对迷你批次使用极限/偏移量以外的其他方式)
  3. 验证已成功完成

解决方法

问题是我不需要sql子句中的偏移量,因为左联接已经过滤掉了新记录。消除偏移会加快并修复作业。

将sql输出保存到变量并打印puts result.cmd_status有助于验证每个批处理是否成功完成。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...