Devo aggiornare tabelle di 1 o 2 miliardi di righe con vari valori per ogni riga. Ogni esecuzione apporta circa 100 milioni di modifiche (10%). Il mio primo tentativo è stato di raggrupparli in una transazione di 300.000 aggiornamenti direttamente su una partizione specifica poiché Postgresql non sempre ottimizza le query preparate se si utilizzano le partizioni.
- Transazioni del gruppo di "UPDATE myTable SET myField=value WHEREmyId=id"
Fornisce 1.500 aggiornamenti/sec. il che significa che ogni corsa richiederebbe almeno 18 ore. - La soluzione HOT aggiorna come descritto qui con FILLFACTOR=50. Fornisce 1.600 aggiornamenti/sec. Uso gli SSD, quindi è un miglioramento costoso in quanto raddoppia le dimensioni dello spazio di archiviazione.
- Inserisci in una tabella temporanea di valore aggiornato e uniscili dopo con UPDATE...FROM Fornisce 18.000 aggiornamenti/sec. se faccio un VACUUM per ogni partizione; 100.000 in su/s altrimenti. Cooool.
Ecco la sequenza delle operazioni:
CREATE TEMP TABLE tempTable (id BIGINT NOT NULL, field(s) to be updated,
CONSTRAINT tempTable_pkey PRIMARY KEY (id));
Accumula un sacco di aggiornamenti in un buffer a seconda della RAM disponibile Quando è pieno, devi cambiare tabella/partizione o completato:
COPY tempTable FROM buffer;
UPDATE myTable a SET field(s)=value(s) FROM tempTable b WHERE a.id=b.id;
COMMIT;
TRUNCATE TABLE tempTable;
VACUUM FULL ANALYZE myTable;
Ciò significa che una corsa ora richiede 1,5 ore invece di 18 ore per 100 milioni di aggiornamenti, vuoto incluso. Per risparmiare tempo, non è necessario eseguire un'aspirazione PIENA alla fine, ma anche un'aspirazione veloce e regolare è utile per controllare l'ID della transazione sul database e non ottenere un'aspirazione automatica indesiderata durante le ore di punta.