Como posso verificar se meu DB precisa de mais RAM?

11

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?

SDReyes
fonte
8
Não há necessidade de verificar, você sempre precisa de mais RAM. :)
Alex Howansky
1
Não é uma questão de programação, estou votando para movê-lo para ServerFault.
GManNickG
1
Eu não sou um DBA, mas começaria vendo que todas as consultas comuns estão à beira de serem unidas por hash em vez de mesclar um loop aninhado. Há alguns ajustes de configuração de banco de dados que você pode fazer que podem afetar a quantidade de memória disponível para qualquer consulta específica [verifique os documentos ou envie por e-mail a lista de discussão é minha sugestão]. Também pode ser útil verificar se você possui RAM suficiente para manter as tabelas mais usadas em cache. Mas, em última análise, a menos que seu DB INTEIRO caiba na RAM, você poderá usar mais. :)

Respostas:

14

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.

Matthew Wood
fonte
9

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

insira a descrição da imagem aqui

cristão
fonte
1

Também funciona, como dito no documento Heroku:

SELECT
    'cache hit rate' AS name,
     sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) AS ratio
FROM pg_statio_user_tables;
Felipe
fonte