Dando sequência ao Tuning Linux do mês passado para baixa latência do PostgreSQL, agora houve uma pilha gigante de testes feitos em dois sistemas de arquivos, três patches e dois conjuntos de parâmetros de ajuste do kernel executados. O resultado até agora são alguns novos dados interessantes, e mais uma melhoria comprometida nesta área que está no PostgreSQL 9.1 agora (fazendo três no total, os outros dois são patches de monitoramento). Falarei sobre a prática recomendada no próximo mês durante uma de minhas palestras no PostgreSQL East, e também enviei algo nessa área para o PGCon de maio. Aqui vou falar um pouco mais sobre os becos sem saída também, enquanto essas memórias ainda estão frescas.
O problema básico aqui é que a forma como o PostgreSQL usa o cache do sistema operacional ao escrever permite que grandes quantidades de dados se acumulem. O resultado quando os pontos de verificação do banco de dados terminam podem ser longos atrasos enquanto aguarda a gravação desses dados. Acontece que o programa pgbench que vem com o PostgreSQL é muito bom em criar esse problema, então foi isso que usei para todos os testes. As perguntas de meios que me propus a responder foram:
- A mudança do antigo sistema de arquivos ext3 realmente mostra uma melhoria de desempenho nas tarefas do banco de dados? Eu escrevi algo sobre o Return of XFS no Linux no ano passado que mostrou uma boa melhoria em benchmarks simples. Isso nem sempre se traduz em melhorias no banco de dados.
- Os ajustes recentes do Linux dirty_bytes e dirty_background_bytes realmente melhoram a latência do pior caso?
- Quais das alterações de banco de dados sugeridas para melhorar o comportamento aqui realmente funcionam?
Você pode ver todos os resultados do teste se quiser verificar os dados brutos. O que foi alterado para cada conjunto de teste é documentado e, se você detalhar um teste individual, poderá ver os parâmetros do banco de dados usados e algumas outras informações básicas do sistema operacional. Essa página da web é o que sai do meu programa de teste pgbench-tools, se você quiser experimentar esse tipo de coisa.
Os resultados não foram muito surpreendentes, mas foram interessantes. Todos os testes aqui foram feitos com dois tamanhos de banco de dados. Em um tamanho de banco de dados menor (escala =500, cerca de um banco de dados de 8 GB que cabe facilmente nos 16 GB de RAM do servidor), o ext3 gerenciava 690 transações/segundo, enquanto com o dobro desse tamanho (escala =1.000, cerca de um banco de dados de 16 GB) era muito mais procuram ligado e só conseguiu 349 TPS. O XFS aumentou esses dois números para 1757 TPS e 417 TPS – um ganho de 255% e 19%, respectivamente. Melhor ainda, a latência do pior caso para uma única transação caiu do intervalo de 34 a 56 segundos (!) para o intervalo de 2 a 5 segundos. Embora até 5 segundos não seja ótimo, essa é uma carga de trabalho sintética projetada para tornar esse problema muito ruim. Os números ext3 são tão terríveis que você ainda provavelmente terá um problema desagradável aqui, mesmo que eu estivesse realmente vendo um comportamento melhor nesse sistema de arquivos do que vi em kernels anteriores (isso foi feito com 2.6.32).
Rodada 1: O XFS vence em uma vitória esmagadora. Não posso recomendar o ext3 como um sistema de arquivos viável em sistemas Linux com muita memória se você planeja escrever muito; simplesmente não funciona nesse contexto. Este servidor tinha apenas 16 GB de RAM, então você pode imaginar o quão ruim é esse problema em um servidor de produção sério aqui em 2011.
Em seguida, os ajustáveis dirty_bytes e dirty_background_bytes. Esses dois melhoraram bastante a latência no ext3, às custas de algumas lentidão. O pior deles, tempo de manutenção lento executando VACUUM, você não vê nos próprios resultados do teste; Eu já discuti isso na minha entrada anterior no blog. No XFS, ajustar esses parâmetros é um desastre de desempenho. Na escala de banco de dados menor, o desempenho do TPS cai 46% e, além disso, a latência fica pior.
Rodada 2: Não espere nenhum milagre de dirty_bytes ou dirty_background_bytes. Eles parecem ter algum efeito positivo em algumas circunstâncias, mas a desvantagem potencial também é grande. Certifique-se de testar com cuidado e inclua VACUUM em seu teste, antes de ajustar esses dois para baixo.
Em seguida, acabei avaliando três ideias de patch para o PostgreSQL como parte deste último CommitFest:
- Espalhe a sincronização do ponto de verificação para chamadas de disco (fsync) ao longo do tempo. Tivemos algum sucesso com isso em um servidor cliente ocupado quando combinado com uma manipulação aprimorada de como outras operações de sincronização eram armazenadas em cache pelo banco de dados
- Solicitações fsync compactas. Essa ideia surgiu do primeiro e se transformou em um patch escrito por Robert Haas. A ideia é que os clientes que tentam sincronizar dados com o disco podem estar competindo com a gravação do ponto de verificação. O que o patch faz é permitir que os clientes limpem a fila de solicitações fsync se a encontrarem cheia.
- Ordenar gravações de ponto de verificação. O conceito é que, se você escrever as coisas na ordem em que o banco de dados acredita que as coisas estão armazenadas no disco, o sistema operacional poderá escrever com mais eficiência. Este patch apareceu há alguns anos com alguns resultados de benchmark sugerindo que funcionou, mas na época ninguém conseguiu replicar as melhorias. A ideia se encaixou bem no restante do trabalho e eu a avaliei novamente.
Rodada 3: Após semanas tentando tudo isso, a única abordagem desse conjunto que mostrou a melhoria em quase todos os tamanhos de carga de trabalho foi a compactação fsync. O código de sincronização de ponto de verificação de propagação original ajudou um pouco nessa área, mas a implementação específica que agora está confirmada para 9.1 funcionou ainda melhor. Foi um ganho quase geral de 10% na maioria dos testes pesados de gravação que fiz. Isso é uma grande melhoria para o PostgreSQL 9.1, e deve eliminar completamente um problema que vimos causar uma lentidão muito maior nos sistemas de produção aqui.
O resto das ideias aqui não receberam uma avaliação tão positiva após pesadas benchmarking, então, por enquanto, eles voltam para a prateleira. Continuarei a coletar dados aqui – alguns testes ext4 são a próxima coisa lógica a tentar – e depois retornarei ao desenvolvimento novamente. Obter um ganho de 10% em algumas cargas de trabalho difíceis é certamente bom, mas ainda há muitos comportamentos de pior caso aqui para considerar os problemas de sincronização de ponto de verificação um assunto encerrado.