Um dos meus servidores PostgreSQL hospeda vários (1-3) bancos de dados que recebem um fluxo constante de dados. Os dados não são particularmente estruturados, equivalem ao tempo atual e a uma variedade de dados observados para aquele instante específico. A taxa de dados é bastante alta; ele chega a cerca de um gigabyte por dia para um banco de dados, cerca de um décimo disso para outro. Não espero que essa taxa aumente. O desempenho de leitura é uma prioridade muito menor e atualmente é aceitável.
Nos logs tenho esta mensagem:
LOG: checkpoints are occurring too frequently (15 seconds apart)
HINT: Consider increasing the configuration parameter "checkpoint_segments".
Esse valor está atualmente definido como 16, cortesia de pgtune
.
Quais são as configurações que devo considerar para melhorar o desempenho de gravação? Eu preferiria manter o máximo de segurança possível. Considerando o volume de dados que chegam, eu poderia aceitar perder alguns dados recentes em uma falha, desde que a maior parte dos dados estivesse intacta.
Edit: Estou usando o PostgreSQL 9.0 por enquanto, mas pretendo atualizar para 9.1. Não estou postando os detalhes de hardware porque embora reconheça sua importância, no final das contas precisarei fazer essa otimização em várias máquinas com hardwares muito diversos. Se o hardware for essencial para a resposta, por favor, forneça as informações gerais para que eu possa aplicar a resposta em máquinas com diferentes configurações de hardware.
1 Gigabyte por dia não é uma carga de gravação tão alta. Espalhados ao longo do dia, isso chega a cerca de 50kbytes por segundo. Um pen drive USB lento poderia lidar com isso. Eu estou supondo que é mais bursty embora. Como sugere a_horse_with_no_name, aumente os segmentos de checkpoint. 100 ou mais não é fora do comum.
Em seguida, aumente o seu
checkpoint_timeout
para 1 hora, bem como aumente o seucheckpoint_completion_target
para algo mais próximo de 1,0 (100%). O alvo de conclusão informa ao PostgreSQL com que agressividade escrever em segundo plano para que esteja x% completo antes de executar um ponto de verificação, o que força todos os dados a serem gravados de uma só vez a partir do WAL e retardará o sistema a um rastreamento enquanto está acontecendo.A razão pela qual você geralmente não define como 100% é que é muito comum gravar no mesmo bloco mais de uma vez e, ao atrasar as gravações do WAL no armazenamento principal, você evita que o mesmo bloco seja gravado duas vezes sem motivo.
Se for improvável que você esteja escrevendo no mesmo bloco mais de uma vez antes que seu tempo limite ocorra, ou seja, tudo o que você faz é inserir, então defini-lo bem alto faz sentido aumentá-lo para 0,9 ou mais. O pior que pode acontecer é você escrever com um pouco mais de frequência do que o necessário, mas o impacto dos pontos de verificação será bastante reduzido.
Em um sistema muito 'gravado', é provável que você seja limitado pela taxa que o WAL pode ser gravado durante a atividade de pico.
Se você realmente pode "aceitar a perda de alguns dados recentes em uma falha", pode desativar o commit síncrono que:
Se você puder alterar seu hardware, considere qualquer uma dessas opções para otimizar as gravações:
--editar
Com base no seu comentário na excelente resposta de @Scott: "O volume de gravação é quase completamente uniforme" e a taxa de dados implícita de "50kbytes por segundo", duvido que você precise fazer algo que arrisque perda de dados. Talvez ajude saber para que alguns de seus outros parâmetros de configuração estão definidos.
Você também pode verificar a frequência/tamanho de seus commits: recentemente me deparei com um problema em que estava tentando atualizar > 1 milhão de registros em uma única transação. Recebi mensagens de log semelhantes às descritas pelo OP, mas a transação não pôde ser concluída mesmo após várias horas. Quando dividi a gravação em várias transações menores (10.000 registros ou mais), o tempo total necessário caiu para cerca de 15 minutos.
O que eu acho que aconteceu foi que o Postgres gastou tanto tempo escrevendo os logs que checkpoint_timeout passou antes que pudesse fazer um progresso substancial salvando os registros. Não tenho certeza se essa explicação se sustenta. Ainda recebo os avisos, mas todas as gravações são eventualmente processadas. No entanto, eu precisava (e encontrei) uma solução programática em vez de uma que exigisse a reconfiguração do banco de dados.
Consulte também http://www.postgresql.org/docs/9.3/static/wal-configuration.html