it-swarm.it

Configurazione di PostgreSQL per le prestazioni di scrittura

Uno dei miei server PostgreSQL ospita diversi (1-3) database che ricevono un flusso costante di dati. I dati non sono particolarmente strutturati, ammontano al tempo corrente e ad una varietà di dati osservati per quel particolare istante. La velocità dei dati è piuttosto elevata; funziona a circa un gigabyte al giorno per un database, circa un decimo di quello per un altro. Non mi aspetto che questo tasso aumenti. Le prestazioni di lettura hanno una priorità molto più bassa ed è attualmente accettabile.

Nei registri ho questo messaggio:

LOG:  checkpoints are occurring too frequently (15 seconds apart)
HINT:  Consider increasing the configuration parameter "checkpoint_segments".

Questo valore è attualmente impostato su 16, per gentile concessione di pgtune.

Quali sono le impostazioni che dovrei considerare per migliorare le prestazioni di scrittura? Preferirei mantenere la massima sicurezza possibile. Considerando il volume di dati in arrivo, potrei accettare di perdere alcuni dati recenti in caso di errore purché la maggior parte dei dati fosse intatta.

Modifica: sto usando PostgreSQL 9.0 per ora, ma ho intenzione di aggiornare a 9.1. Non sto pubblicando i dettagli hardware perché, mentre riconosco la loro importanza, alla fine dovrò fare questa ottimizzazione su più macchine con hardware molto diverso. Se l'hardware è essenziale per la risposta, forniscimi le informazioni generali in modo da poter applicare la risposta a macchine con diverse configurazioni hardware.

30
Daniel Lyons

1 Gigabyte al giorno non è così elevato di un carico di scrittura. Distribuito per tutto il giorno, arriva a circa 50 kbyte al secondo. Una chiavetta USB lenta potrebbe gestirlo. Presumo però che sia più scoppiettante. Come suggerisce a_horse_with_no_name, aumenta i segmenti del checkpoint. 100 o giù di lì non è fuori dal comune.

Quindi aumenta il tuo checkpoint_timeout a 1 ora, oltre a cercare di aumentare il tuo checkpoint_completion_target a qualcosa di più vicino all'1,0 (100%). Il target di completamento dice a PostgreSQL quanto aggressivamente scrivere in background in modo che sia x% completo prima di eseguire un checkpoint, che forza tutti i dati da scrivere immediatamente dal WAL e rallenta il sistema a una scansione mentre sta accadendo.

Il motivo per cui di solito non lo si imposta al 100% è che è abbastanza comune scrivere nello stesso blocco più di una volta e, ritardando le scritture WAL nello store principale, si impedisce che lo stesso blocco venga scritto due volte senza motivo.

Se è improbabile che tu scriva sullo stesso blocco più di una volta prima che si verifichi il timeout, ovvero tutto ciò che fai è inserire, quindi impostarlo su un valore abbastanza alto ha senso alzarlo a 0,9 o giù di lì. Il peggio che accadrà è che scriverai un po 'più spesso di quanto potresti altrimenti fare, ma l'impatto dei punti di controllo sarà notevolmente ridotto.

24
Scott Marlowe

In un sistema molto 'write heavy', è probabile che tu sia limitato dalla velocità che WAL può scrivere durante l'attività di picco.

Se riesci davvero a "accettare la perdita di alcuni dati recenti in caso di errore" puoi disattivare commit sincrono che:

può essere un'alternativa utile quando le prestazioni sono più importanti della certezza esatta sulla durata di una transazione

Se sei in grado di cambiare l'hardware, potresti considerare uno di questi per ottimizzare le scritture:

  • RAID10 su RAID5
  • Molti mandrini (ad esempio potrebbe significare 2,5 "anziché 3,5")
  • SAS su SATA
  • 15K su 10K unità
  • SSD

--modificare

Sulla base del tuo commento su @ risposta eccellente di Scott : "Il volume di scrittura è in realtà quasi completamente uniforme", e la velocità di dati implicita di "50kbyte al secondo", dubito che tu debba fare tutto ciò che rischia di dati perdita. Forse sarebbe utile sapere su quali altri parametri di configurazione sono impostati.

Potresti anche verificare la frequenza/dimensione dei tuoi commit: di recente ho riscontrato un problema in cui stavo cercando di aggiornare> 1 milione di record in una singola transazione. Ho ricevuto messaggi di registro simili a quelli descritti da OP, ma la transazione non è stata completata anche dopo diverse ore. Quando ho suddiviso la scrittura in diverse transazioni più piccole (10.000 record circa), il tempo totale richiesto è sceso a circa 15 minuti.

Quello che I think è successo è che Postgres ha trascorso così tanto tempo a scrivere i log che checkpoint_timeout trascorso prima che potesse compiere progressi sostanziali salvando i record. Non sono sicuro se questa spiegazione regge. Ricevo ancora gli avvisi, ma alla fine tutte le scritture vengono elaborate. Tuttavia, avevo bisogno (e trovato) una soluzione programmatica piuttosto che una che richiedesse la riconfigurazione del database.

Vedi anche http://www.postgresql.org/docs/9.3/static/wal-configuration.html

5
Sarah Messer