it-swarm.it

PostgreSQL: forza i dati in memoria

Esiste un modo sistematico per forzare PostgreSQL a caricare una tabella specifica in memoria o almeno a leggerla dal disco in modo che venga memorizzata nella cache dal sistema?

34
Adam Matan

Potresti essere interessato a uno dei argomenti delle mailing list , è risposto da Tom Lane (sviluppatore principale):

[..] Ma la mia opinione è che le persone che pensano di essere più intelligenti di un algoritmo di memorizzazione nella cache LRU sono in genere sbagliate. Se la tabella è molto utilizzata, rimarrà nella memoria bene. Se non è sufficientemente usato per rimanere in memoria secondo un algoritmo LRU, forse lo spazio di memoria dovrebbe davvero essere speso per qualcos'altro. [..]

Potresti anche essere interessato a una SO domanda: https://stackoverflow.com/questions/486154/postgresql-temporary-tables e forse più adatto https://stackoverflow.com/questions/407006/need-to-load-the-whole-postgresql-database-into-the-ram

27
DrColossos

Postgres 9.4 ha infine aggiunto un'estensione per precaricare i dati dalle relazioni nel sistema operativo o nella cache del buffer del database (a scelta):

pg_prewarm

Ciò consente di raggiungere le prestazioni operative più rapidamente.

Esegui una volta nel database (istruzioni dettagliate qui ):

CREATE EXTENSION pg_prewarm;

Quindi è semplice precaricare qualsiasi relazione. Esempio di base:

SELECT pg_prewarm('my_tbl');

Trova la prima tabella denominata my_tbl nel percorso di ricerca e lo carica nella cache del buffer Postgres

O:

SELECT pg_prewarm('my_schema.my_tbl', 'prefetch');

prefetch invia richieste di prefetch asincrone al sistema operativo, se supportate, o genera un errore in caso contrario. read legge l'intervallo richiesto di blocchi; a differenza di prefetch, questo è sincrono e supportato su tutte le piattaforme e build, ma potrebbe essere più lento. buffer legge l'intervallo richiesto di blocchi nella cache del buffer del database.

L'impostazione predefinita è buffer, che ha il maggiore impatto (costo più elevato, effetto migliore).

Leggi il manuale per maggiori dettagli , le virgolette sono da lì.
Depesz bloggato anche a questo proposito.

39

In generale, se hai abbastanza RAM puoi generalmente fidarti del servizio di database per fare un buon lavoro nel mantenere le cose che usi regolarmente nella RAM. Alcuni sistemi ti permettono di suggerire che la tabella dovrebbe essere sempre tenuto in RAM (che è utile per tabelle di piccole dimensioni che non vengono utilizzate spesso ma quando vengono utilizzate è importante che rispondano il più rapidamente possibile) ma se pgsql ha una tabella di questo tipo ti suggerisce è necessario fare molta attenzione a usarli poiché si sta riducendo la quantità di memoria disponibile per la memorizzazione nella cache di qualsiasi altra cosa in modo da poter rallentare l'applicazione in generale.

Se stai cercando di adescare la cache della pagina del database all'avvio (ad esempio dopo un riavvio o un'altra operazione di mantenimento che fa dimenticare al DB tutto ciò che viene memorizzato nella cache), scrivi uno script che procede come segue:

SELECT * FROM <table>
SELECT <primary key fields> FROM <table> ORDER BY <primary key fields>
SELECT <indexed fields> FROM <table> ORDER BY <indexed fields>

(l'ultimo passaggio ripetuto per ciascun indice o corso e fare attenzione a disporre i campi nella clausola ORDER BY nell'ordine corretto)

Dopo aver eseguito quanto sopra, ogni pagina di dati e indice dovrebbe essere letta e così sarà nella RAM cache della pagina (almeno per il momento). Abbiamo script come questo per i nostri database di applicazioni, che vengono eseguiti dopo il riavvio in modo che i primi utenti che accedono al sistema in seguito non abbiano una risposta più lenta. È meglio scrivere a mano qualsiasi script di questo tipo, invece di scansionare le tabelle di definizione del db (come sys.objects/sys.indexes/sys.columns in MSSQL), quindi puoi scansionare in modo selettivo gli indici più comunemente usati anziché scansionare tutto che richiederà più tempo.

4
David Spillett

Ho avuto un problema simile:
Dopo aver riavviato il servizio server e tutti i dati incassati sono stati eliminati, molte query sono state chiamate la prima volta in cui erano davvero molto lente, a causa della complessità specifica delle query, fino a quando tutti gli indici e i dati necessari sono stati incassati. ciò significa, ad esempio, che gli utenti devono colpire una volta ogni "elemento" (1-3 secondi di esecuzione) e dati relativi da 50 milioni di righe, in modo che gli utenti non subiscano più ritardi indesiderati. Gli utenti impiegano le prime 3 ore a sperimentare fastidiosi blocchi, fino a quando i dati più utilizzati non vengono incassati e i programmi stanno rovinando il primato con le prestazioni di produzione, terminando anche allora, 2 giorni alcuni improvvisi ritardi brevi, quando colpiscono meno dati al primo accesso ... , per dati statistici ecc.

Per risolvere questo problema, ho scritto un piccolo python che esegue le selezioni sulle tabelle utilizzate più pesanti con indici di grandi dimensioni. Sono stati necessari 15 minuti per l'esecuzione e nessun ritardo nelle prestazioni.

1
LongBeard_Boldy

Uso RamDrive da QSoft, che era benchmarking come il ramdisk più veloce per Windows. Ho appena usato

initdb -D e:\data

dove e:\è il posto di RamDisk.

0
David

Hmmm, potrebbe essere il comando COPIA sarebbe d'aiuto. Basta eseguire COPY per stdout e leggere da esso. È possibile farlo usando pg_dump:

pg_dump -U <user> -t <table> <database> > /dev/null

L'altro modo è trovare tutti i file di tabella ed eseguire cat <files> > /dev/null.

Ecco l'esempio su come ottenere i nomi dei file delle tabelle:

# SELECT oid, datname FROM pg_database ;
  oid  |  datname  
-------+-----------                                                                                                                                          
<...>
 16384 | test
-- out of database is 16384
# SELECT oid, relname FROM pg_class WHERE relname like 'fn%';
  oid  | relname 
-------+---------
 24576 | fn
(1 row)
-- oid of our table is 24576

quindi, i file della tabella sono/path/to/pgsql/data/base/16384/24576 *

Ti piacerebbe leggere anche gli indici e le tabelle dei toast, ottenere il loro oid allo stesso modo.

A proposito, perché ne hai bisogno? Credo che postgresql e il sistema operativo siano abbastanza intelligenti da memorizzare nella cache i dati più caldi e mantenerli in buono stato. efficienza della cache.

0
rvs