paint-brush
Back-end eficiente, desempenho superior: um mergulho profundo na otimização de serviços da Webby@sergeidzeboev
958
958

Back-end eficiente, desempenho superior: um mergulho profundo na otimização de serviços da Web

Sergei Dzeboev8m2023/11/21
Read on Terminal Reader

Otimizar o back-end de um serviço da web vai além de apenas melhorar o código e os algoritmos. A chave para aumentar a eficiência do serviço é otimizar as interações com o banco de dados. Isso pode ser alcançado por meio do ajuste fino de consultas ORM, usando classes de dados simples, categorizando adequadamente os dados como Quentes, Quentes ou Frios e empregando estratégias eficazes de armazenamento em cache. Essas etapas levam a um serviço web mais eficiente, responsivo e de alto desempenho.
featured image - Back-end eficiente, desempenho superior: um mergulho profundo na otimização de serviços da Web
Sergei Dzeboev HackerNoon profile picture
0-item


A otimização do backend de um serviço web visa sempre aumentar o seu desempenho, cujo aspecto fundamental é a aceleração do processamento de dados. Este processo engloba muitas melhorias importantes que visam tornar mais eficiente o uso dos recursos e minimizar o tempo de resposta do sistema às solicitações. Neste artigo, compartilharei várias técnicas comprovadas que podem acelerar significativamente o seu serviço web.


Em que focar para melhorar?

Muitos programadores, em sua busca para tornar um aplicativo mais rápido, concentram-se na otimização do código e dos algoritmos, escolhendo estruturas de dados adequadas e operações ideais. Isso normalmente leva a um melhor desempenho, muitas vezes melhorando a velocidade do código otimizado, mas não substancialmente.


O modesto aumento se deve à velocidade inerente às operações de memória, e melhorias significativas não deveriam ser esperadas, a menos que o código original fosse muito ineficiente. No entanto, certas operações demoradas devem ser priorizadas para otimização, especialmente operações de entrada-saída.


Seja trabalhando com arquivos ou interagindo com um banco de dados, o tempo de execução dessas tarefas é sempre notável em comparação com as operações na memória. Você não pode influenciar significativamente o processo de leitura de dados de um arquivo, mas trabalhar com o banco de dados está sob seu controle direto. Como desenvolvedor, você tem todos os recursos para melhorar significativamente essa interação.


Vamos explorar as estratégias a seguir para tornar o trabalho com seu banco de dados mais eficiente, aumentando significativamente o desempenho do seu serviço de back-end


Otimizar consultas

Hoje, é raro encontrar um serviço web de back-end que não utilize um sistema de mapeamento objeto-relacional (ORM) para interações de banco de dados. Se você deseja resultados de alto nível, considere personalizar o ORM. Embora os ORMs sejam eficientes e livres de erros, eles são projetados para uso geral. Essa ampla aplicabilidade geralmente ocorre às custas do alto desempenho.


Lembre-se de que os ORMs são criados para serem compatíveis com vários bancos de dados, o que pode significar perder vantagens específicas do banco de dados selecionado para o seu projeto. Por exemplo, conforme ilustrado aqui, aproveitar recursos exclusivos de banco de dados pode aumentar significativamente a velocidade das interações com o banco de dados em até 30 vezes.


Em vez de depender apenas das consultas padrão fornecidas por um ORM, vale a pena criar suas próprias consultas otimizadas. As consultas personalizadas geralmente apresentam melhor desempenho, especialmente em cenários que envolvem múltiplas junções.


Abaixo está um exemplo simples no Spring JPA de como você pode melhorar o desempenho usando uma consulta de junção:

 @Transactional @Lock(LockModeType.PESSIMISTIC_READ) @Query(value = """ SELECT e FROM EmployeeRecord e LEFT JOIN DepartmentRecord d ON e.departmentId = d.id WHERE e.departmentId = :departmentId; """) List<EmployeeRecord> findEmployeesByDepartmentId(Integer departmentId);


Use classes planas

O uso de classes complexas com objetos aninhados e um sistema hierárquico profundo pode levar a uma perda significativa no desempenho do sistema. Muitas vezes é desnecessário consultar o banco de dados para obter toda a estrutura aninhada, especialmente quando nem todas as classes da estrutura são totalmente utilizadas.


Embora a inicialização lenta ajude a mitigar consultas desnecessárias em objetos aninhados, surgem desafios quando um objeto aninhado é necessário, mas nem todos os seus dados são necessários. A solução para esse dilema é empregar classes de dados simples.


Você deve criar uma classe projetada para coletar apenas os dados de campo necessários do banco de dados. Em seguida, com uma consulta personalizada ao banco de dados incorporando todas as junções necessárias, selecione apenas os campos que são realmente necessários.


Essa abordagem não apenas aumentará a velocidade da consulta, mas também reduzirá o tráfego de dados do banco de dados para o seu serviço.


Por exemplo, usando NamedParameterJdbcTemplate do Spring JPA, uma classe simples com os campos necessários pode ser criada:

 public record EmployeeDepartment(Integer employeeId, String employeeName, String departmentName) { }


A seguir, usando um script simples, apenas os campos necessários são coletados das tabelas principais e unidas:

 public List<EmployeeDepartment> employeeDepartments() { return template.query(""" SELECT employees.employee_id, employees.employee_name, departments.department_name FROM employees LEFT JOIN departments ON employees.department_id = departments.department_id; """, new MapSqlParameterSource(), employeeDepartmentMapper); }


Essa abordagem reduzirá significativamente a carga e tornará o trabalho com dados muito mais eficiente.


Definir dados importantes

A próxima etapa importante no trabalho com dados é definir os tipos de dados, sendo o tipo principal Hot Data.


Hot Data são os dados que o serviço processa em tempo real. Estes dados não podem ser armazenados em cache porque a relevância da resposta do serviço web depende da sua capacidade de resposta imediata. Portanto, esses dados devem estar sempre atualizados. O serviço trabalha consistentemente com Hot Data, registrando continuamente novos valores e extraindo informações para atualizações oportunas.


Para trabalhar com Hot Data da forma mais eficiente possível, é fundamental garantir que a tabela na qual ele está armazenado permaneça o mais compacta possível.


  • Mantenha o mínimo de colunas possível

    Sua tabela deve conter apenas os campos que são usados ativamente e armazenar todos os outros dados em uma tabela separada, retendo apenas o ID da linha relevante. Essa abordagem permite acessar todos os campos não utilizados quando necessário, como para fins de relatório, sem sobrecarregar a tabela principal com esses dados.


  • Mantenha o mínimo de linhas possível

    Não armazene linhas que você não precisa mais. Em vez disso, mova-os para a tabela de arquivo. Essa abordagem permite que suas consultas encontrem as linhas necessárias com mais rapidez, preservando todos os dados históricos em um arquivo. Automatizar esse processo com um trabalho simples minimiza o seu envolvimento no arquivamento de dados.


  • Mantenha os índices atualizados

    Lembre-se de construir índices. Os índices são cruciais para pesquisas rápidas de dados e muitas vezes são esquecidos pelos programadores. A indexação adequada pode reduzir significativamente o tempo de pesquisa e o consumo de memória do seu banco de dados. Certifique-se de criar índices para condições e colunas envolvidas em junções, incluindo índices compostos.


  • Desista de usar chaves estrangeiras

    O uso de chaves estrangeiras coloca uma carga adicional no banco de dados para garantir que a chave exista na tabela associada, o que retarda as operações de dados, especialmente ao gravar dados. Não me interpretem mal; armazenar uma chave estrangeira em tal tabela é possível e às vezes até necessário, mas é melhor armazenar a chave simplesmente como um valor simples.


Esses métodos simples permitirão maximizar a eficiência e a utilidade de sua mesa.


Definir dados quentes

Warm Data são dados usados para preparar uma resposta, embora sua relevância não tenha um impacto crítico. Os exemplos incluem descrições de produtos ou uma lista de acessórios disponíveis. Ao armazenar esses dados, não é mais necessário monitorar de perto o tamanho da tabela. Porém, é importante não descurar a criação de índices nessas tabelas, pois elas são frequentemente utilizadas para junções.


  • Dados quentes em cache

    Uma vantagem importante do Warm Data é sua capacidade de cache. Uma vez feita a solicitação, você pode armazenar os dados na memória, reduzindo o número de chamadas ao banco de dados e agilizando os cálculos. No entanto, lembre-se de que o cache precisa de atualizações regulares.


  • Defina TTL (Time To Live) razoável

    Defina o Time To Live (TTL) correto para operação adequada. Normalmente, um TTL de cerca de 90 segundos é suficiente, alinhando-se com o tempo médio que um usuário leva para tomar uma decisão e fazer um pedido em um site. Sempre ajuste o TTL com base nos requisitos do seu serviço.


  • Use classes menores para armazenar dados quentes

    Para armazenamento em cache, use classes compactas. Mesmo quando consultas completas são feitas e todos os dados das tabelas são coletados, evite armazenar tudo no cache. Armazene apenas os dados necessários. Essa abordagem reduz significativamente o consumo de memória do seu serviço de back-end.


A configuração do Warm Data não exigirá muito tempo e, no final das contas, você alcançará resultados tangíveis.


Definir dados frios

Dados frios referem-se a dados que raramente mudam, mas que são necessários para uma resposta. Exemplos de tais dados incluem o nome ou endereço de uma loja. Estes dados mudam muito raramente e têm um impacto mínimo na relevância da resposta.


  • Armazene dados frios em cache ou armazene-os em um arquivo

    Este tipo de dados deve sempre ser armazenado em cache. Se não for viável colocar esses dados na memória devido ao seu grande tamanho, considere descarregá-los do banco de dados e armazená-los em arquivos em formato pronto para uso. Dividi-lo em categorias e selecionar apenas as usadas com mais frequência ajudará a reduzir o uso de memória. Além disso, esta abordagem melhora visivelmente a velocidade em comparação com a obtenção de dados do banco de dados, pois elimina a necessidade de trabalhar na rede.


  • Atualizar cache no gatilho

    O tempo de vida (TTL) desse cache é normalmente definido em 24 horas. Para manter o cache atualizado, você deve agendar uma tarefa ou criar um gatilho que monitore as alterações nesses dados e inicie uma atualização do cache. Por exemplo, se um endpoint for chamado para postar ou atualizar Cold Data, um gatilho deverá ser ativado para atualizar o cache.


O gerenciamento eficaz de Cold Data também é uma parte importante da otimização da eficiência da resposta, melhorando assim o desempenho geral do sistema.


Conclusão

Concluindo, a otimização do backend de um serviço web não depende apenas da otimização do código e do algoritmo. O aprimoramento das interações com o banco de dados levará a uma maior eficiência e desempenho geral do serviço. A implementação de técnicas como o ajuste fino de consultas ORM (Mapeamento Objeto-Relacional), a utilização de classes de dados planas, a definição precisa de tipos de dados e a adoção de estratégias de cache podem aumentar significativamente o desempenho do serviço. Através destas medidas, o serviço web acabará por alcançar maior eficiência, capacidade de resposta e funcionalidade geral melhorada.


Etapas principais :

  1. Otimize as consultas ao banco de dados e evite depender apenas de implementações de ORM.
  2. Use classes simples para reduzir o uso de memória e aumentar a velocidade das respostas.
  3. Defina os tipos de dados categorizando-os como Quente, Quente ou Frio.
  4. Empregue estratégias específicas adaptadas a cada tipo de dados definido.