Quem sou eu

sábado, 5 de dezembro de 2009

Otimizando a performance do seu banco de dados no PostgreSQL

Quem trabalha com informática fatalmente vai ter que mexer com tudo. No início você trabalha somente com redes ou com desenvolvimento de software, mas atualmente as duas áreas estão cada vez mais integradas.
O desenvolvedor de software tem que conhecer cada vez mais de redes, segurança e protocolos de comunicação para desenvolver um software eficiente, que consuma poucos recursos, seja seguro e tenha qualidade. Já o administrador de redes, precisa conhecer o desenvolvimento de software para conseguir monitorar as aplicações que funcionam no seu servidor, verificar questões de segurança e em alguns momentos desenvolver scripts ou pequenos programas que auxiliem na administração da rede e dos servidores.
O novo desafio que peguei pela frente foi fazer a otimização de um servidor de banco de dados PostgreSQL.
A necessidade surgiu após fazer a análise do funcionamento do servidor durante um período de produção. A CPU do servidor estava trabalhando sempre acima de 75% e a memória sempre abaixo de 15%.
Algumas partes do sistema estavam extremamente lentas, principalmente a tela de consulta de log de transações realizadas e o detalhamento de cada transação.
Antes de iniciarmos a conversa sobre otimização, vamos a alguns números do Banco de Dados e do servidor em questão:
  • Servidor: Dell PowerEdge Quad Xeon 2.33 Ghz, 4GB RAM, 1TB HD
  • Quantidade de tabelas: 50
  • Tamanho atual do banco: 5,3 GB
O banco de dados possui 4 principais tabelas que recebem inúmeros INSERTs por dia. A estimativa é que sejam inseridos no banco de dados todos os dias cerca de 1.000.000 de registros (Putz! Haja registro! Mas vamos em frente... vai dar certo! hehehe).
Lendo um pouco sobre o PostgreSQL e sobre Banco de Dados, cheguei à conclusão que para melhorar o desempenho era necessário:
  1. Melhorar a estrutura de tabelas do banco de dados
  2. Realizar algumas configurações no PostgreSQL
  3. Programar manutenções diárias no banco de dados
Antes de executar as modificações, realizei o acesso à página de logs do sistema (nessa página a consulta é realizada por data e em um dia de consulta o retorno é de aproximadamente 110.000 registros) e ao detalhamento de um dos logs. Resultado:
  • Tempo para carregar página de logs: 4,53 segundos
  • Tempo para carregar detalhamento: 35,42 segundos

O primeiro passo é melhorar a estrutura do banco de dados através da criação de índices nos campos que são geralmente usados na clásula where do SQL.
Analisei as consultas e encontrei os principais campos em cada tabela. É importante observar que não adianta criar índices em todos os campos de todas as tabelas, se não a CPU do seu servidor vai para as alturas.
A análise da consulta pode ser feita usando o comando EXPLAIN ANALYZE. Basta executar EXPLAIN ANALYZE seguido do seu select que está lento e você vai ter um resumo do tempo consumido em cada parte da sua consulta e a partir daí você saberá quais os campos são necessários criar um índice.
Mas antes de melhorarmos os índices do nosso banco de dados, vamos fazer uma limpeza geral de registros que foram deletados mas que o banco de dados ainda não os removeu por completo, apenas marcou os registros como apagados. Fazemos isso através do comando VACUUM FULL.
Este comando não pode ser executado frequentemente, já que ele dá um lock nas tabelas na hora que está fazendo a operação. É importante que você faça a manutenção do seu Banco de Dados para evitar o uso deste comando. Falarei sobre estas operações no meu próximo post.
O comando VACUUM FULL demora um pouco para ser executado, dependendo do tamanho do seu banco de dados. No meu caso, demorou 103 segundos, ou seja, 1 min e 43 segundos.
Agora vamos criar os índices das tabelas. A criação dos índices é feita usando o comando CREATE INDEX seguido do comando ANALYZE tabela, exemplo:
  • CREATE INDEX log_chamada_id_idx1 on log_operacao_cti(log_chamada_id)
Onde log_chamada_id_idx1 é o nome do índice, log_operacao_cti é o nome da tabela e log_chamada_id é o campo da tabela que eu desejo criar um índice.
  • ANALYZE log_operacao_cti
Resultado da criação dos índices no meu banco de dados:


Agora que temos índices criados nas nossas tabelas, vamos realizar um novo teste no sistema para ver como está o tempo de carregamento.
Resultado após as alterações:
  • Tempo para carregar a página de logs: 1,46 segundos
  • Tempo para carregar o detalhamento: 492 ms

Percebeu a diferença? :)
O próximo passo é melhorar a configuração do servidor PostgreSQL para que ele consuma os recursos disponíveis no hardware de forma mais eficiente e programar manutenções no banco de dados para mantermos o banco sempre limpo e funcionando perfeitamente, mas isto é assunto para um próximo post.

Nenhum comentário:

Postar um comentário