Postgres default values as a backfill method
Often, I want to add a new column to a Postgres table with a default value for new records, but also want existing records to have a different value. Changing Postgres default value can make this a very fast operation.
Let’s see an example. Let’s assume we have a songs
table, and we want to add a liked
column. Existing records need to have the value be set to false
, while new values have it set to true
.
Table and initial data setup:
CREATE TABLE songs (
name character varying NOT NULL
);
-- CREATE TABLE
-- Time: 16.084 ms
INSERT INTO songs(name) VALUES ('Stairway To Heaven');
-- INSERT 0 1
-- Time: 0.590 ms
SELECT * FROM songs;
-- name
-- --------------------
-- Stairway To Heaven
-- (1 row)
--
-- Time: 0.652 ms
Now, let’s add the new column with a default value of false
. That is not our end-goal, but it will add that value to existing records1:
ALTER TABLE songs
ADD COLUMN liked boolean DEFAULT false;
-- ALTER TABLE
-- Time: 3.745 ms
SELECT * FROM songs;
-- name | liked
-- --------------------+-------
-- Stairway To Heaven | f
-- (1 row)
--
-- Time: 0.672 ms
ALTER TABLE songs
ALTER COLUMN liked SET NOT NULL;
-- ALTER TABLE
-- Time: 1.108 ms
Now, if we change the default value to true
, and insert a new record:
ALTER TABLE songs ALTER COLUMN liked SET DEFAULT true;
-- ALTER TABLE
-- Time: 4.664 ms
INSERT INTO songs(name) VALUES ('Hotel California');
-- INSERT 0 1
-- Time: 1.447 ms
SELECT * FROM songs;
--
-- name | liked
-- --------------------+-------
-- Stairway To Heaven | f
-- Hotel California | t
-- (2 rows)
--
-- Time: 0.791 ms
As we can see, we have the schema in the shape that we want, and the correct data stored in it, without needing a “traditional” backfill to modify each existing row manually. The default value method is much faster, since Postgres doesn’t need to update each record, just check the default value when they were created. 👍🏻
-
Stairway To Heaven is excellent. I’m not implying that I don’t like it. I do. It’s an anthem. ↩
Find me on Mastodon at @ylansegal@mastodon.sdf.org,
or by email at ylan@{this top domain}
.