PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Il modo migliore per eliminare milioni di righe per ID

Tutto dipende...

  • Presupponendo nessun accesso in scrittura simultaneo ai tavoli coinvolti o potresti dover bloccare esclusivamente i tavoli o questo percorso potrebbe non essere adatto a te.

  • Elimina tutti gli indici (possibilmente tranne quelli necessari per l'eliminazione stessa).
    Ricreali in seguito. In genere è molto più veloce degli aggiornamenti incrementali degli indici.

  • Verifica se disponi di trigger che possono essere eliminati/disabilitati temporaneamente in sicurezza.

  • Le chiavi esterne fanno riferimento alla tua tabella? Si possono eliminare? Eliminato temporaneamente?

  • A seconda delle impostazioni dell'autovuoto, potrebbe aiuto per eseguire VACUUM ANALYZE prima dell'operazione.

  • Alcuni dei punti elencati nel relativo capitolo del manuale Popolare un Database potrebbe anche essere utile, a seconda della configurazione.

  • Se elimini grandi porzioni della tabella e il resto si inserisce nella RAM, il modo più semplice e veloce potrebbe essere questo:

BEGIN; -- typically faster and safer wrapped in a single transaction

SET LOCAL temp_buffers = '1000MB'; -- enough to hold the temp table

CREATE TEMP TABLE tmp AS
SELECT t.*
FROM   tbl t
LEFT   JOIN del_list d USING (id)
WHERE  d.id IS NULL;      -- copy surviving rows into temporary table

TRUNCATE tbl;             -- empty table - truncate is very fast for big tables

INSERT INTO tbl
SELECT * FROM tmp;        -- insert back surviving rows.
-- ORDER BY ?             -- optionally order favorably while being at it

COMMIT;

In questo modo non è necessario ricreare viste, chiavi esterne o altri oggetti dipendenti. E ottieni un tavolo incontaminato (ordinato) senza gonfiarsi.

Leggi i temp_buffers impostazione nel manuale. Questo metodo è veloce fintanto che la tabella si adatta alla memoria, o almeno la maggior parte di essa. Il wrapper delle transazioni protegge dalla perdita di dati se il tuo server si arresta in modo anomalo durante questa operazione.

Esegui VACUUM ANALYZE dopo. Oppure VACUUM FULL ANALYZE se vuoi portarlo alla dimensione minima (prende il blocco esclusivo). Per i tavoli grandi considera le alternative CLUSTER / pg_repack o simili:

  • Ottimizza l'intervallo di query del timestamp di Postgres

Per i tavolini, un semplice DELETE invece di TRUNCATE è spesso più veloce:

DELETE FROM tbl t
USING  del_list d
WHERE  t.id = d.id;

Leggi le Note sezione per TRUNCATE nel manuale. In particolare (come ha sottolineato anche Pedro nel suo commento):

TRUNCATE non può essere utilizzato su una tabella che ha riferimenti a chiavi esterne da altre tabelle, a meno che anche tutte queste tabelle non vengano troncate nello stesso comando. [...]

E:

TRUNCATE non attiverà alcun ON DELETE trigger che potrebbero esistere per le tabelle.