Reputation: 5145
I wonder what's the best way to deal with slow migrations when you have a large user base?
For example, I am moving the email column of users to a user_emails table to allow multiple emails by user. So, I've a migration that look like this:
class MoveLegacyPrimaryEmailToUserEmails < ActiveRecord::Migration
def change
users = User.all
users.each do |user|
user_email = UserEmail.new
user_email.user_id = user.id
user_email.email = user.legacy_primary_email
user_email.save!
user.primary_user_email_id = user_email.id
user.save!
end
end
end
According to a simulation I've done, it will take ~ 66 minutes to run. To speed things up and avoid downtime, I've transformed this into raw SQL statements:
class MoveLegacyPrimaryEmailToUserEmails < ActiveRecord::Migration
def change
execute <<-SQL
INSERT INTO user_emails (email, user_id)
SELECT legacy_primary_email, id FROM users;
SQL
execute <<-SQL
UPDATE users
INNER JOIN user_emails
ON users.legacy_primary_email = user_emails.email
SET users.primary_user_email_id = user_emails.id;
SQL
end
end
Is this the correct way of dealing with this kind of issues or I am missing something obvious?
Upvotes: 1
Views: 36
Reputation: 4296
I usually see this tackled with a multi-stage deployment:
Having said that, I don't like babysitting hours-long deployments. If you can make it fast by writing raw SQL, do it. If that makes it fast enough to do the deployment in a single step, bonus!
Upvotes: 1