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

Come velocizzare le prestazioni di inserimento in PostgreSQL

Vedi popolare un database nel manuale di PostgreSQL, l'eccellente articolo di depesz sull'argomento e questa domanda SO.

(Nota che questa risposta riguarda il caricamento in blocco dei dati in un DB esistente o la creazione di uno nuovo. Se sei interessato, il DB ripristina le prestazioni con pg_restore o psql esecuzione di pg_dump output, gran parte di questo non si applica da pg_dump e pg_restore già eseguire operazioni come la creazione di trigger e indici al termine di un ripristino schema+dati) .

C'è molto da fare. La soluzione ideale sarebbe importare in un UNLOGGED tabella senza indici, quindi cambiala in loggata e aggiungi gli indici. Sfortunatamente in PostgreSQL 9.4 non c'è supporto per la modifica delle tabelle da UNLOGGED a loggato. 9.5 aggiunge ALTER TABLE ... SET LOGGED per permetterti di farlo.

Se puoi portare offline il tuo database per l'importazione in blocco, usa pg_bulkload .

Altrimenti:

  • Disattiva tutti i trigger sul tavolo

  • Elimina gli indici prima di avviare l'importazione, ricreali in seguito. (Ci vuole molto meno tempo per costruire un indice in un passaggio rispetto ad aggiungere gli stessi dati progressivamente e l'indice risultante è molto più compatto).

  • Se si esegue l'importazione all'interno di una singola transazione, è possibile eliminare i vincoli di chiave esterna, eseguire l'importazione e ricreare i vincoli prima di eseguire il commit. Non eseguire questa operazione se l'importazione è suddivisa su più transazioni poiché potresti introdurre dati non validi.

  • Se possibile, usa COPY invece di INSERT s

  • Se non puoi utilizzare COPY considera l'utilizzo di INSERT multivalore s se pratico. Sembra che tu lo stia già facendo. Non cercare di elencare anche molti valori in un unico VALUES anche se; quei valori devono rientrare nella memoria un paio di volte, quindi mantienilo a poche centinaia per istruzione.

  • Combina i tuoi inserti in transazioni esplicite, eseguendo centinaia di migliaia o milioni di inserimenti per transazione. Non esiste un limite pratico AFAIK, ma il batching ti consentirà di recuperare da un errore contrassegnando l'inizio di ogni batch nei dati di input. Ancora una volta, sembra che tu lo stia già facendo.

  • Usa synchronous_commit=off e un enorme commit_delay per ridurre i costi di fsync(). Tuttavia, questo non sarà di grande aiuto se hai raggruppato il tuo lavoro in grandi transazioni.

  • INSERT o COPY in parallelo da più collegamenti. Quanti dipendono dal sottosistema del disco dell'hardware; come regola pratica, se si utilizza l'archiviazione collegata diretta, si desidera una connessione per disco rigido fisico.

  • Imposta un max_wal_size alto valore (checkpoint_segments nelle versioni precedenti) e abilita log_checkpoints . Guarda i log di PostgreSQL e assicurati che non si lamenti dei checkpoint che si verificano troppo frequentemente.

  • Se e solo se non ti dispiace perdere l'intero cluster PostgreSQL (il tuo database e qualsiasi altro sullo stesso cluster) a causa di una corruzione catastrofica se il sistema si arresta in modo anomalo durante l'importazione, puoi interrompere Pg, impostare fsync=off , avvia Pg, esegui l'importazione, quindi (vitalmente) ferma Pg e imposta fsync=on ancora. Vedi configurazione WAL. Non farlo se ci sono già dei dati che ti interessano in qualsiasi database sulla tua installazione di PostgreSQL. Se imposti fsync=off puoi anche impostare full_page_writes=off; di nuovo, ricorda solo di riattivarlo dopo l'importazione per prevenire il danneggiamento del database e la perdita di dati. Vedi le impostazioni non durevoli nel manuale Pg.

Dovresti anche esaminare la messa a punto del tuo sistema:

  • Usa buona qualità SSD per l'archiviazione il più possibile. I buoni SSD con cache write-back affidabili e con protezione dell'alimentazione rendono le velocità di commit incredibilmente più veloci. Sono meno utili se segui i consigli di cui sopra, il che riduce i flush del disco / il numero di fsync() s - ma può comunque essere di grande aiuto. Non utilizzare SSD economici senza un'adeguata protezione da interruzione di corrente a meno che non ti interessi conservare i tuoi dati.

  • Se stai utilizzando RAID 5 o RAID 6 per l'archiviazione collegata diretta, fermati ora. Eseguire il backup dei dati, ristrutturare l'array RAID su RAID 10 e riprovare. RAID 5/6 sono senza speranza per le prestazioni di scrittura di massa, anche se un buon controller RAID con una grande cache può aiutare.

  • Se hai la possibilità di utilizzare un controller RAID hardware con una grande cache di write-back con batteria tampone, questo può davvero migliorare le prestazioni di scrittura per carichi di lavoro con molti commit. Non aiuta molto se stai usando un commit asincrono con un commit_delay o se stai facendo meno grandi transazioni durante il caricamento in blocco.

  • Se possibile, memorizza WAL (pg_wal o pg_xlog nelle vecchie versioni) su un disco/array di dischi separato. Non ha senso usare un filesystem separato sullo stesso disco. Le persone spesso scelgono di utilizzare una coppia RAID1 per WAL. Anche in questo caso, questo ha più effetto sui sistemi con tassi di commit elevati e ha scarso effetto se stai utilizzando una tabella non registrata come destinazione del caricamento dei dati.

Potresti anche essere interessato a Optimize PostgreSQL per test rapidi.