Almost all Ruby on Rails developers might come across scenario where they need to add a new column with a default value to one of the database tables. Most of us (including me) would write following migration statement -
add_column :table_name, :column_name, :boolean, default: false
This is a good practice but would cause downtime if the table has large number of records. It took 3 secs
when I ran the migration for a table having 50k records.
-- add_column(:table_name, :column_name, :boolean, {:default=>false})
-> 3.3695s
3 secs
is a long time for production applications that cant afford downtime for a single second.
One of the faster way is to separate single migration statement into two statements.
add_column :table_name, :column_name, :boolean, default: false
to
add_column :table_name, :column_name, :boolean
change_column_default :table_name, :column_name, false
Migration took 0.24 sec to complete on same table having 50k records.
-- add_column(:table_name, :column_name, :boolean)
-> 0.0014s
-- change_column_default(:table_name, :column_name, false)
-> 0.0220s
Super fast - 12.5x faster than previous method.
Note - This method will not update default values of existing records. To update existing records, you need to write a background job/rake task that will simply execute single SQL query to update all existing records with default value.