Añadir una columna con valores default en PostgreSQL

Hay operaciones en bases de datos que mantienen lockeos algún tiempo en una tabla, y son buenas.

Hay operaciones en bases de datos que mantienen lockeos menos tiempo, y son mejores.

Y hay operaciones que no lockean las tablas. Ésas son las impresindibles.

Hoy vamos a ver diferencias al añadir una columna con un valor por defecto en PostgreSQL.

Tenemos una tabla, empresas:


padronafip=# \d empresas;
 Table "public.empresas"
 Column    |     Type      | Modifiers
 --------------+---------------+-----------
 cuit         | numeric(11,0) | not null
 denominacion | character(30) |
 Indexes:
 "empresas_pkey" PRIMARY KEY, btree (cuit)

Y vamos a añadir un campo ’empleador’ para saber si la empresa tiene o no tiene empleados, pero queremos que si no le decimos nada, asuma que no tiene empleados (default=’false’):


postgres@db-server:~$ time echo "ALTER TABLE empresas ADD COLUMN
 empleador boolean default 'false'"|psql padronafip
ALTER TABLE

real    0m39.862s
user    0m0.108s
sys    0m0.064s

Bien, 39 segundos, no estuvo mal. Veamos un poco cómo quedaron los datos:


padronafip=# select * from empresas limit 10;
cuit     |          denominacion          | empleador
-------------+--------------------------------+-----------
20000004759 | SUCESION DE PAEZ DE LA TORRE C | f
20000033481 | SUCESION DE PERROTTA CAYETANO  | f
20000035891 | MULLER CARLOS JORGE            | f
20000129403 | MODUBAR INES                   | f
20000156982 | ORTIZ GARCIA JUAN              | f
20000171345 | KAPLAN ALICIA DORA             | f
20000175499 | SUCESION DE SOLARI BENITO      | f
20000179672 | CANTARELLA ADELINA             | f
20000185036 | SUCESION DE EARNSHAW JUAN ALFR | f
20000189406 | SUCESION DE CAUSARANO ANTONIO  | f
(10 rows)

Ahora, probemos otra aproximación al mismo problema:


postgres@db-server:~$ time echo "ALTER TABLE empresas ADD COLUMN
 empleador boolean;
ALTER TABLE empresas ALTER COLUMN empleador
SET DEFAULT 'false'"|psql padronafip
ALTER TABLE
ALTER TABLE

real    0m0.197s
user    0m0.028s
sys    0m0.008s

Wow, 0,197 segundos. La diferencia en esta tabla de prueba, es de 39 segundos, ahora, veamos cómo quedaron los datos en nuestra tabla:


padronafip=# select * from empresas limit 10;
cuit     |          denominacion          | empleador
-------------+--------------------------------+-----------
20000004759 | SUCESION DE PAEZ DE LA TORRE C |
20000033481 | SUCESION DE PERROTTA CAYETANO  |
20000035891 | MULLER CARLOS JORGE            |
20000129403 | MODUBAR INES                   |
20000156982 | ORTIZ GARCIA JUAN              |
20000171345 | KAPLAN ALICIA DORA             |
20000175499 | SUCESION DE SOLARI BENITO      |
20000179672 | CANTARELLA ADELINA             |
20000185036 | SUCESION DE EARNSHAW JUAN ALFR |
20000189406 | SUCESION DE CAUSARANO ANTONIO  |
(10 rows)

Bien, en un sistema de producción con alta concurrencia y problemas de lockeos, creo que puedo vivir con esto, ya que me permitió realizar el cambio sin pedir una ventana de mantenimiento.

Entonces, vemos que PostgreSQL realiza una re-escritura de la tabla cuando en la creación de la tabla ponemos el default.

Ojo, que si necesitamos añadirlo con ‘not null’ tendremos que ir por la primera opción (que incluye re-escritura y completar todos los nulls) ya que si intentamos el segundo camino, obtendremos:


postgres@db-server:~$ time echo "ALTER TABLE empresas ADD COLUMN
empleador boolean; ALTER TABLE empresas ALTER COLUMN empleador
SET DEFAULT 'false'; ALTER TABLE empresas ALTER COLUMN empleador
SET NOT NULL"|psql padronafip
ALTER TABLE
ALTER TABLE
ERROR:  column "empleador" contains null values

real    0m1.565s
user    0m0.076s
sys    0m0.004s

One thought on “Añadir una columna con valores default en PostgreSQL

Leave a Reply