Come verifichi se la tua istanza DB postgresql necessita di più memoria RAM per gestire i dati di lavoro attuali?
Come verifichi se la tua istanza DB postgresql necessita di più memoria RAM per gestire i dati di lavoro attuali?
Risposte:
Se tutto ciò che si trova su Linux, la RAM fisica totale dovrebbe essere maggiore della dimensione del database sul disco per ridurre al minimo l'I / O. Alla fine l'intero database sarà nella cache di lettura del sistema operativo e l'I / O sarà limitato al commit delle modifiche sul disco. Preferisco trovare la dimensione del DB eseguendo "du -shc $ PGDATA / base" - quel metodo aggrega tutti i database in un unico numero. Finché sei più grande di quello, dovrebbe andare bene.
Inoltre, puoi consultare la percentuale di riscontri nella cache degli heap e dei recuperi di blocchi di indice. Questi misurano la frequenza degli hit nei buffer condivisi di PostgreSQL. I numeri possono essere un po 'fuorvianti - anche se potrebbe essere stato un errore nella cache dei buffer condivisi, potrebbe comunque essere un successo nella cache di lettura del sistema operativo. Tuttavia, gli hit nei buffer condivisi sono ancora meno costosi degli hit nella cache di lettura del sistema operativo (che, a loro volta, sono meno costosi di un paio di ordini di grandezza rispetto al dover tornare sul disco).
Per esaminare la percentuale di hit dei buffer condivisi, utilizzo questa query:
SELECT relname, heap_blks_read, heap_blks_hit,
round(heap_blks_hit::numeric/(heap_blks_hit + heap_blks_read),3)
FROM pg_statio_user_tables
WHERE heap_blks_read > 0
ORDER BY 4
LIMIT 25;
Questo ti dà i 25 peggiori trasgressori in cui manca la cache del buffer per tutte le tabelle in cui è stato necessario recuperare almeno un blocco dal "disco" (di nuovo, che potrebbe essere la cache di lettura del sistema operativo o l'I / O del disco effettivo). È possibile aumentare il valore nella clausola WHERE o aggiungere un'altra condizione per heap_blks_hit per filtrare le tabelle utilizzate di rado.
La stessa query di base può essere utilizzata per verificare la percentuale di hit dell'indice totale per tabella sostituendo globalmente la stringa "heap" con "idx". Dai un'occhiata a pg_statio_user_indexes per ottenere una suddivisione per indice.
Una breve nota sui buffer condivisi: una buona regola empirica per questo in Linux è di impostare il parametro di configurazione shared_buffers su 1/4 di RAM, ma non più di 8 GB. Questa non è una regola rigida, ma piuttosto un buon punto di partenza per l'ottimizzazione di un server. Se il tuo database ha solo 4 GB e hai un server da 32 GB, 8 GB di buffer condivisi sono effettivamente eccessivi e dovresti essere in grado di impostarlo su 5 o 6 GB e avere ancora spazio per la crescita futura.
Ho creato questo SQL per mostrare il rapporto tra tabelle e hit del disco:
-- perform a "select pg_stat_reset();" when you want to reset counter statistics
with
all_tables as
(
SELECT *
FROM (
SELECT 'all'::text as table_name,
sum( (coalesce(heap_blks_read,0) + coalesce(idx_blks_read,0) + coalesce(toast_blks_read,0) + coalesce(tidx_blks_read,0)) ) as from_disk,
sum( (coalesce(heap_blks_hit,0) + coalesce(idx_blks_hit,0) + coalesce(toast_blks_hit,0) + coalesce(tidx_blks_hit,0)) ) as from_cache
FROM pg_statio_all_tables --> change to pg_statio_USER_tables if you want to check only user tables (excluding postgres's own tables)
) a
WHERE (from_disk + from_cache) > 0 -- discard tables without hits
),
tables as
(
SELECT *
FROM (
SELECT relname as table_name,
( (coalesce(heap_blks_read,0) + coalesce(idx_blks_read,0) + coalesce(toast_blks_read,0) + coalesce(tidx_blks_read,0)) ) as from_disk,
( (coalesce(heap_blks_hit,0) + coalesce(idx_blks_hit,0) + coalesce(toast_blks_hit,0) + coalesce(tidx_blks_hit,0)) ) as from_cache
FROM pg_statio_all_tables --> change to pg_statio_USER_tables if you want to check only user tables (excluding postgres's own tables)
) a
WHERE (from_disk + from_cache) > 0 -- discard tables without hits
)
SELECT table_name as "table name",
from_disk as "disk hits",
round((from_disk::numeric / (from_disk + from_cache)::numeric)*100.0,2) as "% disk hits",
round((from_cache::numeric / (from_disk + from_cache)::numeric)*100.0,2) as "% cache hits",
(from_disk + from_cache) as "total hits"
FROM (SELECT * FROM all_tables UNION ALL SELECT * FROM tables) a
ORDER BY (case when table_name = 'all' then 0 else 1 end), from_disk desc