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”