https://docs.djangoproject.com/en/1.10/topics/migrations/
Here it says: "PostgreSQL is the most capable of all the databases here in terms of schema support; the only caveat is that adding columns with default values will cause a full rewrite of the table, for a time proportional to its size.
"For this reason, it’s recommended you always create new columns with null=True, as this way they will be added immediately."
I am asking if I get it correct. From what I understand, I should first create the field with null=True and no default value then migrate it and then give it a default value and migrate it again, the values will be added immediately, but otherwise the whole database would be rewritten and Django migration doesn't want to do the trick by itself?
ALTER TABLE "auth_user" ADD COLUMN "preference" integer DEFAULT 0 NOT NULL; ALTER TABLE "auth_user" ALTER COLUMN "preference" DROP DEFAULT; COMMIT; The first SQL statement adds the column and fills all existing rows with the default value.
you can either: temporarily remove your migration, execute python manage.py migrate, add again your migration and re-execute python manage.py migrate. Use this case if the migrations refer to different models and you want different migration files for each one of them.
It's also mentioned in that same page that:
In addition, MySQL will fully rewrite tables for almost every schema operation and generally takes a time proportional to the number of rows in the table to add or remove columns. On slower hardware this can be worse than a minute per million rows - adding a few columns to a table with just a few million rows could lock your site up for over ten minutes.
and
SQLite has very little built-in schema alteration support, and so Django attempts to emulate it by:
Creating a new table with the new schema Copying the data across Dropping the old table Renaming the new table to match the original name
So in short, what that statement you are referring to above really says is
postgresql exhibits mysql like behaviour when adding a new column with a default value
The approach you are trying would work. Adding a column with a null would mean no table re write. You can then alter the column to have a default value. However existing nulls will continue to be null
The way I understand it, on the second migration the default value will not be written to the existing rows. Only when a new row is created with no value for the default field it will be written.
I think the warning to use null=True for new column is only related to performance. If you really want all the existing rows to have the default value just use default= and accept the performance consequence of a table rewrite.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With