Il modo più efficiente per aggiungere una colonna seriale a una tabella enorme


10

Qual è il modo più veloce per aggiungere una colonna BIGSERIAL a una tabella enorme (~ 3 righe Bil., ~ 174Gb)?

MODIFICARE:

  • Voglio che la colonna sia valori incrementati per le righe esistenti ( NOT NULL).
  • Non ho impostato un fattore di riempimento (che sembra una cattiva decisione in retrospettiva).
  • Non ho problemi con lo spazio su disco, voglio solo che sia il più veloce possibile.

Risposte:


12

Cosa c'è di sbagliato in:

ALTER TABLE foo ADD column bar bigserial;

Verrà riempito automaticamente con valori univoci (a partire da 1).

Se si desidera un numero per ogni riga esistente, è necessario aggiornare ogni riga della tabella . O no?

La tabella sarà gonfiata al doppio della sua dimensione se non può riutilizzare le tuple morte o lo spazio libero nelle pagine di dati. Le prestazioni dell'operazione potrebbero trarre FILLFACTORgrandi benefici da un numero inferiore a 100 o solo tuple morte casuali sparse sul tavolo. Altrimenti potresti voler eseguire in VACUUM FULL ANALYZEseguito per recuperare spazio su disco. Questo non sarà veloce, però.

pgstattuple
Potresti essere interessato a questa estensione. Ti aiuta a raccogliere statistiche sui tuoi tavoli. Per scoprire le tuple morte e lo spazio libero:

Installa l'estensione una volta per banca dati:

CREATE EXTENSION pgstattuple;

Chiamata:

SELECT * FROM pgstattuple('tbl');

Alternativa

Se puoi permetterti di creare una nuova tabella, che si spezzerebbe a seconda delle viste, delle chiavi esterne, ...

Crea una copia vuota della vecchia tabella:

CREATE new_tbl AS
SELECT *
FROM   old_tbl
LIMIT  0;

Aggiungi la colonna bigserial:

ALTER new_tbl ADD column bar bigserial;

INSERIRE i dati dalla vecchia tabella, riempiendo automaticamente il bigserial:

INSERT INTO new_tbl
SELECT *    --  new column will be filled with default
FROM   old_tbl
ORDER  BY something; -- or don't order if you don't care: faster

La nuova colonna bigserial non è presente in SELECT di INSERT e verrà riempita automaticamente con il valore predefinito . È possibile precisare tutte le colonne e aggiungere nextval()alla SELECTlista nello stesso senso.

Assicurati di avere tutti i tuoi dati nella nuova tabella.
Aggiungi indici, vincoli, trigger che avevi nella vecchia tabella ora .

DROP TABLE old_tbl;
ALTER TABLE new_tbl RENAME TO old_tbl;

Potrebbe essere nel complesso un po 'più veloce. Questo ti lascia con un tavolo alla vaniglia (e indici) senza alcun gonfiamento.

È necessario spazio libero su disco - intorno alle dimensioni della tabella precedente, a seconda dello stato della tabella - come spazio di manovra. Ma potresti aver bisogno di altrettanto con il primo metodo semplice a causa del gonfiamento della tabella. Ancora una volta, i dettagli dipendono dallo stato della tabella.


3
Avvolgi l'alternativa in un'unica transazione, che sarà molto più veloce. fsync
Eviterà
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.