Como você verificaria se sua instância de banco de dados postgresql precisa de mais memória RAM para manipular seus dados de trabalho atuais?
Como você verificaria se sua instância de banco de dados postgresql precisa de mais memória RAM para manipular seus dados de trabalho atuais?
Respostas:
Se você estiver no Linux, sua RAM física total deverá ser maior que o tamanho do banco de dados em disco para minimizar a E / S. Eventualmente, todo o banco de dados estará no cache de leitura do SO e a E / S será limitada a confirmar as alterações no disco. Eu prefiro encontrar o tamanho do banco de dados executando "du -shc $ PGDATA / base" - esse método agrega todos os bancos de dados em um único número. Contanto que você seja maior que isso, tudo ficará bem.
Além disso, você pode observar a taxa de acertos do cache de buscas de heap e bloco de índice. Eles medem a taxa de acertos nos buffers compartilhados do PostgreSQL. Os números podem ser um pouco enganadores - mesmo que tenha sido um erro no cache de buffers compartilhados, ainda pode ser um acerto no cache de leitura do SO. Ainda assim, os hits nos buffers compartilhados ainda são mais baratos que os hits no cache de leitura do SO (que, por sua vez, são menos caros em algumas ordens de magnitude do que ter que voltar ao disco).
Para examinar a taxa de acertos dos buffers compartilhados, eu uso esta consulta:
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;
Isso fornece os 25 piores criminosos em que o cache do buffer está ausente para todas as tabelas em que pelo menos um bloco precisou ser buscado no "disco" (novamente, que poderia ser o cache de leitura do SO ou a E / S do disco). Você pode aumentar o valor na cláusula WHERE ou adicionar outra condição para heap_blks_hit para filtrar as tabelas raramente usadas.
A mesma consulta básica pode ser usada para verificar a taxa de acertos do índice total por tabela, substituindo globalmente a cadeia "heap" por "idx". Dê uma olhada em pg_statio_user_indexes para obter uma análise por índice.
Uma observação rápida sobre buffers compartilhados: uma boa regra geral para isso no Linux é definir o parâmetro de configuração shared_buffers como 1/4 da RAM, mas não mais que 8 GB. Esta não é uma regra rígida, mas sim um bom ponto de partida para ajustar um servidor. Se o seu banco de dados tiver apenas 4 GB e você tiver um servidor de 32 GB, 8 GB de buffers compartilhados serão realmente um exagero e você poderá configurá-lo para 5 ou 6 GB e ainda ter espaço para crescimento futuro.
Eu fiz este SQL para mostrar a tabela vs taxa de acertos do 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