En lugar de crear una nueva tabla, también puede volver a insertar filas únicas en la misma tabla después de truncarla. Hágalo todo en una sola transacción . Opcionalmente, puede eliminar la tabla temporal al final de la transacción automáticamente con ON COMMIT DROP
. Vea abajo.
Este enfoque solo es útil cuando hay muchas filas para eliminar de toda la tabla. Para unos pocos duplicados, use un archivo DELETE
.
Mencionaste millones de filas. Para que la operación sea más rápida , debe asignar suficientes búferes temporales para la sesión. La configuración debe ajustarse antes de que se use cualquier búfer temporal en su sesión actual. Descubra el tamaño de su mesa:
SELECT pg_size_pretty(pg_relation_size('tbl'));
Establecer en temp_buffers
consecuencia. Redondee generosamente porque la representación en memoria necesita un poco más de RAM.
SET temp_buffers = 200MB; -- example value
BEGIN;
-- CREATE TEMPORARY TABLE t_tmp ON COMMIT DROP AS -- drop temp table at commit
CREATE TEMPORARY TABLE t_tmp AS -- retain temp table after commit
SELECT DISTINCT * FROM tbl; -- DISTINCT folds duplicates
TRUNCATE tbl;
INSERT INTO tbl
SELECT * FROM t_tmp;
-- ORDER BY id; -- optionally "cluster" data while being at it.
COMMIT;
Este método puede ser superior a la creación de una nueva tabla si existen objetos dependientes. Vistas, índices, claves externas u otros objetos que hagan referencia a la tabla. TRUNCATE
te hace comenzar con una pizarra limpia de todos modos (nuevo archivo en segundo plano) y es mucho más rápido que DELETE FROM tbl
con tablas grandes (en DELETE
realidad, puede ser más rápido con tablas pequeñas).
Para tablas grandes, normalmente es más rápido eliminar índices y claves externas, rellenar la tabla y volver a crear estos objetos. En lo que respecta a las restricciones de fk, debe estar seguro de que los nuevos datos son válidos, por supuesto, o se encontrará con una excepción al intentar crear el fk.
Tenga en cuenta que TRUNCATE
requiere un bloqueo más agresivo que DELETE
. Esto puede ser un problema para tablas con una carga concurrente y pesada.
Si TRUNCATE
no es una opción o en general para tablas pequeñas a medianas, existe una técnica similar con un CTE de modificación de datos (Postgres 9.1 +):
WITH del AS (DELETE FROM tbl RETURNING *)
INSERT INTO tbl
SELECT DISTINCT * FROM del;
-- ORDER BY id; -- optionally "cluster" data while being at it.
Más lento para mesas grandes, porque TRUNCATE
allí es más rápido. Pero puede ser más rápido (¡y más simple!) Para mesas pequeñas.
Si no tiene ningún objeto dependiente, puede crear una nueva tabla y eliminar la anterior, pero apenas obtiene nada con este enfoque universal.
Para tablas muy grandes que no cabrían en la RAM disponible , crear una nueva tabla será considerablemente más rápido. Tendrá que sopesar esto contra posibles problemas / gastos generales con objetos dependientes.