8 erros para evitar ao lidar com bancos de dados

Post inspirado nesse outro post, de Adrian Colyer (@adriancolyer), sobre o paper “How not to structure your database-backed web applications: a study of performance bugs in the wild“, Yang et al., ICSE’18.


Veja 8 dicas bastante úteis para aplicações que usam banco de dados.

Apesar de os exemplos usarem o Hibernate, as dicas são válidas para aplicações que usam outros frameworks ORM.

Os exemplos estão disponíveis no GitHub, com testes mostrando a diferença de performance.

1. Computação ineficiente

Em vez de fazer cálculos no seu código, deixe o banco de dados fazê-los de forma muito mais eficiente.

Exemplos a evitar:

Nesses casos, você está carregando uma lista inteira de documentos do banco de dados, apenas para saber se existe algum documento, ou para pegar o mais recente.

O banco de dados consegue fazer a computação de forma eficiente, sem precisar trazer os dados do banco, e entregar só o valor que você quer:

2. Computação desnecessária

Geralmente ocorre quando uma query é feita dentro de um loop, mas poderia ser feita fora do loop, evitando repetir um procedimento custoso desnecessariamente.

Exemplo a evitar:

Algumas vezes, é difícil perceber, porque o loop pode estar em um método e a busca em outro:

Nesses casos, a busca pelos interessados poderia acontecer fora do loop:

3. Acesso ineficiente

Acontece quando você não pega todas as informações que precisa em uma query, ou pega dados demais na query. Tem tudo a ver com as palavras “lazy” e “eager“. Também pode ocorrer quando se faz vários updates em vez de fazer tudo em um batch.

Exemplo a evitar:

Nesse caso, para obter a lista de documentos de cada autor, em caça laço do loop a aplicação precisa fazer uma nova query.

Para resolver, você pode já pedir a informação na primeira query:

O contrário também pode acontecer. Você tem algum objeto que será buscado do banco, de forma “EAGER“, mas não será usado.

Exemplo a ser evitado:

Nesse caso, o autor é sempre buscado, mas não usado. Ou seja, buscam-se mais objetos que necessários. Solução usando a API de Criteria:

A solução usando query, é simplesmente buscar apenas as colunas que precisa:

4. Carregamento de dados desnecessários

Geralmente acontece quando você quer só uma propriedade, mas carrega todo o objeto para depois obter a propriedade.

Exemplo a ser evitado:

Como fazer:

5. Campos faltando

Muitas vezes, os campos podem ser calculados facilmente a partir de outras colunas. Mas, às vezes, alguns cálculos são realizados muitas vezes, ou são demorados, o suficiente para valer mais a pena adicionar uma nova coluna no banco.

Digamos que precisamos mostrar na tela do vendedor qual será a comissão de determinada venda. Cada produto possui uma categoria de comissão diferente, e pode dar 2.5%, 4% ou 6%.

Imagine uma query para isso:

Agora, precisamos mostrar quanto de comissão ele já tem acumulado, mas, a cada R$ 2000, a comissão aumenta 10%. Então, a query fica:

Por último, se a equipe inteira de vendas passar de R$ 50000, a comissão de todos também aumenta 5%. Ou qualquer outro fator que o gerente de vendas conseguiu imaginar para tentar estimular a equipe. Ou imagine que o gerente pode, a qualquer momento, mudar as porcentagens das categorias no meio do mês, mas a comissão das vendas já realizadas não pode mudar por causa disso.

E agora? Vale a pena calcular toda vez que o gerente abrir o relatório de comissões e todas as vezes que os 30, 130, ou 300 vendedores atualizarem a página? Ou é melhor guardar o total de comissão de cada venda no banco de dados?

6. Índices faltando

Usar índices é uma das melhores formas de melhorar a performance das consultas. Dê uma olhada sobre índices nas documentações oficiais do MySQL, do PostgreSQL e do MongoDB, por exemplo.

7. Paginação de conteúdo

Em vez de mostrar todos os itens na tela, sempre prefira uma busca paginada. Com o crescimento dos dados no banco, mostrar todos os itens deixará a aplicação cada vez mais lenta.

Exemplo de paginação com Hibernate:

8. Funcionalidade pesada

Algumas vezes, é difícil saber que determinada funcionalidade contribui para a lentidão do sistema. Mas se você descobrir uma consulta lenta, você também pode repensar se a funcionalidade é tão essencial para o usuário, talvez movê-la para outra tela que vai ser menos acessada, ou até remover totalmente essa funcionalidade.

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.