Ottimizzazione di PostgreSQL per dati transitori


8

Ho diverse tabelle con 100-300 colonne di tipi interi ciascuna, che contengono dati altamente volatili. I set di dati sono codificati da una o due chiavi primarie e quando si verifica l'aggiornamento, l'intero set di dati viene eliminato e i nuovi dati vengono inseriti in una transazione. La dimensione del set di dati è in genere di poche centinaia di righe, ma in casi estremi può arrivare a diverse migliaia di righe. L'aggiornamento avviene una volta al secondo e gli aggiornamenti del set di dati per chiavi diverse sono generalmente disgiunti, quindi non è possibile eliminare e ricreare la tabella.

Come posso sintonizzare Postgres per gestire tale carico? Posso usare la versione più recente e più grande se ciò fa la differenza.

Risposte:


7

A seconda del numero di set di dati diversi, un'opzione sarebbe quella di partizionare le tabelle per set di dati.

Quando un set di dati viene aggiornato, BEGINuna nuova transazione, TRUNCATEla tabella, COPYi nuovi dati in esso e COMMIT. PostgreSQL ha un'ottimizzazione in cui COPYl'inserimento in una tabella che è stata TRUNCATEeseguita nella stessa transazione fa molto meno I / O se si sta utilizzando wal_level = minimal(impostazione predefinita).

Se non puoi partizionare e troncare (diciamo, se hai a che fare con decine o centinaia di migliaia di set di dati, dove ci sarebbero troppe tabelle) vorrai invece avviare l'autovacuum per eseguire il più possibile , assicurati di avere buoni indici su tutto ciò che elimini in base a, ed essere pronto per prestazioni piuttosto ordinarie.

Se non hai bisogno di sicurezza in caso di crash - non ti dispiace che i tuoi tavoli siano vuoti dopo un crash del sistema - puoi anche creare i tuoi tavoli UNLOGGED, il che ti farà risparmiare una grande quantità di costi I / O.

Se non ti dispiace dover ripristinare l'intera configurazione da un backup dopo un crash del sistema, puoi fare un ulteriore passo avanti e anche impostare fsync=off, che in pratica dice a PostgreSQL "non preoccuparti della sicurezza degli arresti anomali, ho buoni backup e non mi preoccupo se i miei dati sono permanentemente e totalmente irrecuperabili dopo un arresto anomalo e sono felice di riutilizzarli initdbprima di poter utilizzare nuovamente il mio database ".

Ho scritto qualcosa in più su questo argomento in un thread simile su Stack Overflow sull'ottimizzazione di PostgreSQL per test rapidi ; che menziona l'ottimizzazione del sistema operativo host, separando WAL su un altro disco se non si utilizzano unloggedtabelle, regolazioni del checkpoint, ecc.

Ci sono anche alcune informazioni nei documenti Pg per un caricamento rapido dei dati e impostazioni non durevoli .


Grazie per il suggerimento sulla partizione, non ho mai pensato di usarli in questo caso. Per quanto riguarda le tabelle non bloccate, vuoi dire che finiscono per vuoto dopo il crash del sistema? Non fa alcuna differenza, sono solo curioso.
Alex Tokarev,

1
@AlexTokarev Esatto; dopo che PostgreSQL si chiude in modo impuro (postmaster o segfault di un backend, i cicli di accensione improvvisi del sistema, il backend viene modificato SIGKILL, ecc.) qualsiasi UNLOGGEDtabella può essere TRUNCATEd, quindi sono vuoti all'avvio. Non vengono troncati dopo un arresto e un riavvio puliti, ma non dovresti fare affidamento sul fatto che siano durevoli.
Craig Ringer,

Grazie per la spiegazione. Non ho bisogno della sicurezza dei dati per le tabelle in questione, i dati in essi contenuti sono temporanei e vengono aggiornati dalla fonte ogni secondo. La disattivazione di fsync non è tuttavia un'opzione, in quanto vi sono altre tabelle più tradizionali nello stesso schema che devono essere sicure e recuperabili. Avere l' UNLOGGEDopzione per tavolo è semplicemente fantastico.
Alex Tokarev,

Sto guardando il documento di partizionamento e sembra che potrebbe essere una soluzione (quasi) perfetta al problema. Una domanda però: se avrò una tabella padre per schema e tabelle figlio per contenere i dati, interrogherò i dati dalla tabella padre, giusto? Se esiste una tabella figlio per quell'intervallo, la query la restituirà, in caso contrario restituirà un set di dati vuoto. In tal caso, posso persino eliminare e ricreare tabelle figlio per ogni nuovo batch di dati. Date le circostanze, quale sarà più efficace, TRUNCATEo DROP/CREATE TABLEsequenza?
Alex Tokarev,

@AlexTokarev Ti consiglierei TRUNCATE, personalmente. La zangola DDL ha i suoi costi. Dal momento che stai apportando modifiche con un livello così alto frequentemente, sarà molto importante assicurarti di attivare l'aggressività di autovacuum su pg_catalog.pg_classe altre tabelle di sistema che potrebbero gonfiarsi sotto quel carico di lavoro.
Craig Ringer,
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.