A resposta curta aqui é "tentativa e erro guiados por métricas de monitoramento e desempenho".
Existem algumas regras gerais que devem ajudá-lo a encontrar a área vaga em que você deve começar, mas elas são muito gerais. As diretrizes gerais "número de CPUs e número de discos independentes" são frequentemente citadas, mas é apenas um ponto de partida incrivelmente grosseiro.
O que você realmente precisa fazer é obter métricas robustas de desempenho para o seu aplicativo. Comece a gravar estatísticas.
Não há muito em termos de ferramentas integradas para isso. Existem coisas como o check_postgres
script nagios , o registro do contador de desempenho do sistema Cacti, o coletor de estatísticas do PostgreSQL, etc ... mas não há muito que ajude tudo. Infelizmente, você terá que fazer isso sozinho. Para o lado do PostgreSQL, consulte o monitoramento no manual do PostgreSQL. Existem algumas opções de terceiros, como o Postgres Enterprise Monitor do EnterpriseDB .
Para as métricas em nível de aplicativo mencionadas aqui, você deseja gravá-las em estruturas de dados compartilhadas ou em um banco de dados externo não durável como o Redis e agregá-las à medida que você as grava ou antes de gravá-las no banco de dados PostgreSQL. Tentar registrar diretamente na página distorcerá suas medidas com a sobrecarga criada pelo registro das medidas e piorará o problema.
A opção mais simples é provavelmente um singleton em cada servidor de aplicativos que você usa para registrar estatísticas do aplicativo. Você provavelmente deseja manter uma atualização constante de mín, máx, n, total e média; Dessa forma, você não precisa armazenar cada ponto de estatística, apenas os agregados. Esse singleton pode gravar suas estatísticas agregadas na página a cada x minutos, uma taxa suficientemente baixa para que o impacto no desempenho seja mínimo.
Começar com:
Qual é a latência da solicitação? Em outras palavras, quanto tempo o aplicativo leva para obter uma solicitação do cliente até responder ao cliente. Registre isso agregado por um período de tempo, e não como registros individuais. Agrupe por tipo de solicitação; digamos, por página.
Qual é o atraso de acesso ao banco de dados para cada consulta ou tipo de consulta que o aplicativo executa? Quanto tempo leva para solicitar informações ao banco de dados / armazenar informações até que esteja pronto e possa passar para a próxima tarefa? Novamente, agregue essas estatísticas no aplicativo e grave apenas as informações agregadas no banco de dados.
Como é o seu rendimento? Em um determinado x minuto, quantas consultas de cada classe principal que seu aplicativo executa são atendidas pelo banco de dados?
Para o mesmo intervalo de tempo de x minutos, quantas solicitações de clientes existiam?
Amostrando a cada poucos segundos e agregando nas mesmas janelas de x minutos no banco de dados, quantas conexões de banco de dados havia? Quantos deles estavam ociosos? Quantos estavam ativos? Em inserções? Atualizações? Selecione% s? exclui? Quantas transações houve nesse período? Consulte a documentação do coletor de estatísticas
Mais uma vez, amostrando e agregando no mesmo intervalo de tempo, como eram as métricas de desempenho do sistema host? Quantas leem e quantas E / S de disco de gravação / segundo? Megabytes por segundo de disco lê e grava? Utilização da CPU? Carga média? Uso de RAM?
Agora você pode começar a aprender sobre o desempenho do seu aplicativo correlacionando os dados, criando gráficos, etc. Você começará a ver padrões, a encontrar gargalos.
Você pode aprender que o seu sistema está em cerviz-garrafa INSERT
e UPDATE
é em altas taxas de transação, apesar de bastante baixo / S de disco em megabytes por segundo. Isso sugere que você precisa melhorar o desempenho da liberação do disco com um controlador RAID de cache de write-back suportado por bateria ou alguns SSDs protegidos por energia de alta qualidade. Você também pode usar synchronous_commit = off
se não houver problema em perder algumas transações na falha do servidor e / ou a commit_delay
, para retirar parte da carga de sincronização.
Quando você faz um gráfico de suas transações por segundo com base no número de conexões simultâneas e corrige a taxa de solicitações variável que o aplicativo está vendo, poderá ter uma idéia melhor de onde está o ponto ideal da taxa de transferência.
Se você não possui armazenamento de liberação rápida (BBU RAID ou SSDs rápidos e duráveis), não desejará mais do que um número bastante pequeno de conexões de gravação ativa, talvez no máximo o dobro do número de discos que você possui, provavelmente menos dependendo da organização do RAID , desempenho do disco etc. Nesse caso, nem vale a pena tentativa e erro; basta atualizar seu subsistema de armazenamento para um com liberações rápidas de disco .
Procure pg_test_fsync
uma ferramenta que ajude a determinar se isso pode ser um problema para você. A maioria dos pacotes do PostgreSQL instala essa ferramenta como parte do contrib, portanto você não precisa compilá-la. Se você receber menos do que um par de milhares de ops / segundo em pg_test_fsync
que você urgentemente precisa atualizar o seu sistema de armazenamento. Meu laptop equipado com SSD recebe de 5000 a 7000. Minha estação de trabalho trabalhando com uma matriz RAID 10 de 4 discos de 7200 rpm SATA e write-through (sem cache de gravação) recebe cerca de 80 operações / segundo f_datasync
, até 20 operações / segundo fsync()
; é centenas de vezes mais lento . Compare: laptop com ssd vs estação de trabalho com gravação (sem gravação em cache) RAID 10. O SSD deste laptop é barato e eu não confio necessariamente nele para liberar seu cache de gravação em caso de perda de energia; Eu mantenho bons backups e não os utilizo para dados importantes. Os SSDs de boa qualidade têm o mesmo desempenho, se não melhor, e são duráveis para gravação.
No caso de sua inscrição, recomendo fortemente que você analise:
- Um bom subsistema de armazenamento com descargas rápidas. Não posso enfatizar isso o suficiente. SSDs de boa qualidade com proteção contra falhas de energia e / ou um controlador RAID com cache de write-back protegido por energia.
- Usando
UNLOGGED
tabelas para dados que você pode perder. Agregue-o periodicamente em tabelas registradas. Por exemplo, mantenha os jogos em andamento em tabelas não registradas e escreva as pontuações em tabelas duráveis comuns.
- Usando um
commit_delay
(menos útil com armazenamento de descarga rápida - dica)
- Desativando
synchronous_commit
transações que você pode perder (menos útil com armazenamento de descarga rápida - dica de dica)
- Tabelas de particionamento, especialmente tabelas em que os dados "expiram" e são limpos. Em vez de excluir de uma tabela particionada, descarte uma partição.
- Índices parciais
- Reduzindo o número de índices que você cria. Todo índice tem um custo de gravação.
- Trabalho em lote para transações maiores
- Usando réplicas de espera ativa somente leitura para remover a carga de leitura do banco de dados principal
- O uso de uma camada de armazenamento em cache, como memcached ou redis, para dados que mudam com menos frequência ou podem ficar obsoletos. Você pode usar
LISTEN
e NOTIFY
executar a invalidação de cache usando gatilhos nas tabelas do PostgreSQL.
Em caso de dúvida: http://www.postgresql.org/support/professional_support/
synchronous_commit = off
ou acommit_delay
?