Performance do ORM vs SQL: O que é melhor para seu projeto Node.js?
Acho que todo mundo já passou por aquele momento em que está desenvolvendo um projeto, querendo fazer tudo de forma otimizada, mas se pergunta: “Será que o ORM está fazendo o meu banco de dados ficar lento?”. Eu já passei por isso e, sinceramente, não sabia se deveria continuar usando o ORM ou partir para o SQL puro. E fui pesquisar, no final, decidi trazer algumas respostas para quem, como eu, também fica nessa dúvida. Neste artigo, vamos bater um papo sobre a performance do ORM e do SQL puro, com foco em como isso impacta os projetos em Node.js. No final das contas, o que realmente importa é: qual das duas opções vai dar conta do recado no seu projeto e, claro, como você pode tirar o máximo de performance de cada uma delas.
O que é um ORM e como isso afeta a performance?
Se você é desenvolvedor Node.js e já trabalhou com bancos de dados relacionais, provavelmente já usou algum ORM. Mas o que é isso exatamente? ORM (Object-Relational Mapping) é um tipo de ferramenta que "mapeia" as tabelas do banco de dados para objetos na linguagem de programação. Ou seja, com o ORM, você não precisa escrever SQL para buscar dados, manipular registros ou fazer consultas. A ferramenta faz tudo isso para você. No ecossistema Node, temos vários ORMs populares, como Sequelize, Prisma e TypeORM. Exemplo com Sequelize: Exemplo com Prisma:
Vantagens do ORM:
- Facilidade de uso: ORMs abstraem a complexidade do SQL, tornando mais rápido o desenvolvimento.
- Manutenção simplificada: Mudanças no esquema do banco de dados podem ser gerenciadas por migrations.
- Portabilidade: O mesmo código ORM pode funcionar com diferentes bancos de dados com poucas ou nenhuma modificação.
Desvantagens do ORM:
- Performance: Para operações complexas, ORMs podem gerar queries ineficientes.
- Curva de aprendizado: Algumas ferramentas possuem APIs complexas e exigem conhecimento específico.
- Overhead: O custo adicional de abstrações pode impactar a performance em cenários de alto volume.
🆚
SQL Puro: O controle total sobre as consultas
Agora, se você opta por SQL puro, é como se estivesse conversando diretamente com o banco de dados. Você escreve suas consultas, otimiza elas da forma que achar melhor, e tem o controle total de como os dados são recuperados. Isso é ótimo quando a performance é prioridade.
Vantagens do SQL Puro:
- Performance otimizada: Consultas ajustadas manualmente tendem a ser mais rápidas.
- Flexibilidade: Você tem acesso total aos recursos do banco, como índices personalizados e stored procedures.
- Controle absoluto: Pode lidar melhor com casos de uso complexos.
Desvantagens do SQL Puro:
- Manutenção: Consultas complexas podem ser difíceis de entender e atualizar.
- Maior risco de erros: Sem abstrações, erros de sintaxe e SQL injection tornam-se mais comuns.
- Maior esforço inicial: Escrever e otimizar SQL exige mais conhecimento e tempo.
Benchmarking: ORM vs SQL Puro
Agora vamos dar uma olhada em benchmarks que mostram a diferença de performance entre ORM e SQL puro. Se você acessar o benchmark publicado no AprendaGolang, vai ver que, em operações complexas, SQL puro pode ser até 40% mais rápido que ORMs, dependendo da consulta. Por exemplo:
- Com ORM (Sequelize): Uma consulta simples pode levar algo em torno de 100ms devido ao overhead de abstração.
- Com SQL puro: A mesma consulta no banco pode ser otimizada e levar apenas 50ms. Ou seja, em aplicações com grandes volumes de dados ou consultas complexas, o SQL puro geralmente se sai melhor. Mas para operações mais simples ou quando o foco é agilidade no desenvolvimento, o ORM é um verdadeiro aliado.
Quando usar ORM ou SQL puro?
Use ORM quando:
- O time está focado em entregar rápido e precisa de uma solução mais simples para interação com o banco.
- O projeto tem requisitos de performance moderados (por exemplo, um sistema que não vai lidar com milhões de registros por segundo).
- O time tem pouca experiência com SQL e não quer lidar com a complexidade de escrever queries manuais.
Use SQL puro quando:
- A performance é crítica e você precisa de total controle sobre as consultas.
- Seu sistema precisa lidar com consultas complexas, como JOINs, subqueries, ou consultas analíticas.
- O projeto envolve grandes volumes de dados e você precisa otimizar ao máximo o tempo de resposta.
O melhor dos dois mundos?
Depois de olhar para os prós e contras de cada abordagem, uma coisa fica clara: o ideal é avaliar cada caso e, quando possível, usar o melhor dos dois mundos. Em muitos projetos, você pode usar o ORM para as consultas mais simples e o SQL puro quando a performance for realmente um requisito crítico. Por exemplo, você pode usar Sequelize ou Prisma para as consultas simples de CRUD, mas para aquelas queries pesadas que envolvem muitos dados ou operações complexas, dar preferência ao SQL puro pode fazer toda a diferença. Em resumo, o que deu para perceber é que não existe uma única resposta. O que realmente importa é entender os requisitos do seu projeto e escolher a ferramenta certa para o trabalho. Às vezes, uma mistura dos dois pode ser a escolha mais inteligente.
Conclusão
No final das contas, tanto o ORM quanto o SQL puro têm seus pontos fortes e fracos. Sequelize, Prisma e TypeORM são excelentes para produtividade e flexibilidade, mas, como vimos, quando a performance é crucial, o SQL puro ainda tem sua vantagem. Em fim, como deu para perceber, o ideal é avaliar as necessidades do projeto e, muitas vezes, combinar os dois. Se você ainda está em dúvida, talvez o melhor seja começar com o ORM e, conforme o projeto evolui, otimizar algumas consultas para SQL puro quando for necessário. Afinal, quem não ama uma boa consultinha otimizada, né?
Referências
Com ORM (Sequelize): Uma consulta simples pode levar algo em torno de 100ms devido ao overhead de abstração.
Não sei coo acontece no Node, não sou especialista nele, porém eu uso todo o poder do EloquentORM do Laravel e acompanho todas as queries pelo Laravel DebugBar para otimizá-las e evitar duplicação.
A minha query mais rápida leva 1.6 milisegundos, enquanto a mais lenta leva 5.9ms. Não sei do funcionamento em outras linguagens se o ORM é melhor ou pior, mas com PHP não tenho a necessidade nenhuma de utilizar SQL puro, inclusive é bem capaz da minha consulta sair menos otimizada do que a do Eloquent rsrs. Então esses 100ms estão pouco altos, não acha? Acredito que a infra seja mais preponderante nesse quesito do que o uso de ORMs.
Acho que vai pelo que você falou, as vezes é melhor fazer um app usando apenas o adapador do banco e gerando as queries na mão, e as vezes é melhor usar o ORM pra simplificar as coisas e garantir algumas coisas como proteção a SQL Injection. Não adianta fazer tudo em sqlpuro se o sistema é um backoffice que vai ser usado no máximo por umas 20 pessoas assim como um relatório complexo ou uma api que recebe milhões de transações por minuto e performance é um ponto critico não é o ideal forçar um ORM se o sql puro resolve melhor. Fora isso bom artigo.
Uma abordagem interessante para o melhor dos dois mundos é transformar seus dados diretamente no banco, preparando-os para serem mapeados pela linguagem com uma view ou função que retorna exatamente o que o ORM precisa. Junto com triggers para lidar com operações de update ou insert. Dessa forma, o ORM continua cuidando da integração com a linguagem, mas é o SQL puro que faz o trabalho pesado de verdade!
Uma ideia interessante seria fazer um comparativo com o próprio TabNews que utiliza SQL puro, testar contra as queries complexas de cálculo de TabCoins e TabCash, ou a própria consulta para trazer os comentários do post.
Eu gosto de SQL puro, mas nunca me identifiquei com o estilo de abstração da maioria dos ORMs, mesmo gostando muito do conceito.
Nessa brincadeira cheguei até a criar um ORM pra MySQL com Node.js e gosto bastante dele. A ideia é ser algo bem minimalista e que, principalmente, lembre a sintaxe original do SQL ao ler e escrever a abstração.
Por exemplo, inserindo duas tabelas:
await pool.insert({
table: 'test',
values: [
{
column1: 'foo',
column2: 1,
},
{
column1: 'bar',
column2: 2,
},
],
});
Que nada mais é que uma abstração para:
INSERT INTO `test` (`column1`, `column2`) VALUES (?, ?), (?, ?)
-- params: ['foo', 1, 'bar', 2]
A vantagem aqui é que fica muito mais fácil inserir múltiplas linhas dinamicamente com uma única query, independente do tamanho da lista dos valores, além de oferecer mais segurança por preparar os parâmetros automaticamente.
Já se fosse pra inserir um único valor, acabaria escrevendo mais com o ORM que com SQL puro. Com isso em mente, eu permito o uso do SQL puro para aproveitar a conexão do ORM sem a obrigação de fazer abstrações pra tudo (essa mesma ideia vale para queries extremamente complexas).
recomendo muito o drizzle porque ele é basicamente sql dentro de funções typescript. e se isso nao é suficiente, voce pode usar generics dentro das queries puras. sinceramente o melhor pra esse caso de queries pesadas. só é chatinho de criar tabela nele ou criar migrações mas isso é o de menos
Tai uma briga boa.
Como sou muito old school, prefiro SQL - lembrando ainda que trabalhando direto no SQL voce pode fazer umas magias negras, como determinar o indice que deseja utilizar em uma pesquisa, indices que nao devem ser utilizados, criacao de tabelas fantasmas, views otimizadas, nested subqueries, stored procedures e triggers para agilizar funcoes e por ai vai.
Alias, otimizacao de SQL eh uma escola a parte - depende tantos dos dados, das tabelas, dos indices, das tablespaces, um bom DBA consegue fazer coisas bem sinistras.
Mas tambem eh verdade que 80% das queries sao arroz-com-feijao - o problema justamente eh que nos 20% restante ficam as queries cabeludas.
Como fica ? Meus dois cents:
ORM para o dia-a-dia, entregar o sistema o mais rapipdo possivel (e garantir a papinha das criancas ou o pack de cerveja dos marmanjos)
Quando chegar naqueles pontos-chave, ai da uma parada, respira fundo e faz o SQL na mao e compara com o gerado pelo ORM e usa o que for mais performatico - porque ninguem merece sistema lento por preguica do dev.
Lembrando que tudo isso cai por terra quando o dev sequer sabe escrever uma query direito e sai metendo * em tudo pq é só isso que ele sabe fazer.
Melhor um ORM do que uma query mal escrita, comelona e insegura.
Eu sempre uso sql puro,isso te da mais autonomia,pode ser mais trabalhoso mas te da menos dor de cabeça na hora de manutenção e atualização.
São pontos realmente muito bons a considerar. Eu, gosto de usar SQL à medida que o modelo entidade-relacionamento fica complexo. Fica impossível usar a abstração do ORM à medida que o MER fica mais complexo. A diferença de performance vai se refletir em um bom MER e no uso correto dos SGBDs, independente do uso de ORM/SQL.