Invece di creare una nuova tabella, puoi anche reinserire righe univoche nella stessa tabella dopo averla troncata. Fai tutto in un'unica transazione . Facoltativamente, puoi rilasciare automaticamente la tabella temporanea alla fine della transazione con ON COMMIT DROP
. Vedi sotto.
Questo approccio è utile solo quando sono presenti molte righe da eliminare da tutta la tabella. Per pochi duplicati, usa un semplice DELETE
.
Hai menzionato milioni di righe. Per rendere l'operazione veloce si desidera allocare abbastanza buffer temporanei per la sessione. L'impostazione deve essere regolata prima di utilizzare qualsiasi buffer temporaneo nella sessione corrente. Scopri le dimensioni del tuo tavolo:
SELECT pg_size_pretty(pg_relation_size('tbl'));
Imposta di temp_buffers
conseguenza. Arrotondare generosamente perché la rappresentazione in memoria richiede un po 'più di 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;
Questo metodo può essere superiore alla creazione di una nuova tabella se esistono oggetti dipendenti. Viste, indici, chiavi esterne o altri oggetti che fanno riferimento alla tabella.TRUNCATE
ti fa comunque iniziare con una lavagna pulita (nuovo file in background) ed è molto più veloce che DELETE FROM tbl
con le tabelle grandi ( DELETE
può effettivamente essere più veloce con le tabelle piccole).
Per le tabelle di grandi dimensioni, è regolarmente più veloce eliminare gli indici e le chiavi esterne, riempire nuovamente la tabella e ricreare questi oggetti. Per quanto riguarda i vincoli fk, devi essere certo che i nuovi dati siano ovviamente validi o incapperai in un'eccezione nel tentativo di creare fk.
Si noti che TRUNCATE
richiede un blocco più aggressivo rispetto a DELETE
. Questo potrebbe essere un problema per le tabelle con un carico pesante e simultaneo.
Se TRUNCATE
non è un'opzione o generalmente per tabelle di piccole e medie dimensioni esiste una tecnica simile con un CTE di modifica dei dati (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.
Più lento per tavoli grandi, perché TRUNCATE
lì è più veloce. Ma può essere più veloce (e più semplice!) Per i tavolini.
Se non hai alcun oggetto dipendente, potresti creare una nuova tabella ed eliminare quella vecchia, ma difficilmente ottieni nulla da questo approccio universale.
Per tabelle molto grandi che non si adatterebbero alla RAM disponibile , la creazione di una nuova tabella sarà notevolmente più veloce. Dovrai soppesare questo contro possibili problemi / spese generali con oggetti dipendenti.