Usando um ORM ou SQL simples? [fechadas]


245

Para alguns dos aplicativos que desenvolvi (depois esqueci), escrevi SQL simples, principalmente para o MySQL. Embora eu tenha usado ORMs em python como SQLAlchemy , não fiquei com eles por muito tempo. Normalmente, era a documentação ou a complexidade (do meu ponto de vista) me segurando.

Eu vejo assim: use um ORM para portabilidade, SQL simples se for usar apenas um tipo de banco de dados. Estou realmente procurando conselhos sobre quando usar um ORM ou SQL ao desenvolver um aplicativo que precise de suporte ao banco de dados.

Pensando nisso, seria muito melhor usar apenas um invólucro leve para lidar com inconsistências do banco de dados versus usar um ORM.


Padronização, segurança, facilidade de manutenção, a abstração da linguagem, DRY, etc.
Ben

O desempenho com ORM pode estar próximo do SQL, depende se você o usar corretamente e com as configurações corretas ... Consulte ho para tornar o EF6.x 5x mais rápido: linkedin.com/pulse/…
baHI

Para arquitetura ORM e instruções (o que evitar), aqui está meu outro link: linkedin.com/pulse/…
baHI

O mapeamento objeto-relacional (ORM) já é muito popular em muitas linguagens de programação e uma das melhores alternativas para SQL. Fui inspirado no estilo de encadeamento de métodos para criar CQL para o meu projeto TRIADB. healis.eu/triadb/#latest-release
Athanassios

2
É estúpido que esta questão tenha sido encerrada.
Mitch Wheat

Respostas:


169

ORMs têm alguns recursos interessantes. Eles podem lidar com grande parte do trabalho de copiar colunas do banco de dados em campos de objetos. Eles geralmente lidam com a conversão dos tipos de data e hora do idioma para o tipo de banco de dados apropriado. Eles geralmente lidam com relacionamentos um-para-muitos de maneira muito elegante, instanciando objetos aninhados. Descobri que, se você projetar seu banco de dados com os pontos fortes e fracos do ORM, poupa muito trabalho na entrada e saída de dados do banco de dados. (Você precisará saber como ele lida com o polimorfismo e os relacionamentos muitos-para-muitos, se precisar mapeá-los. São esses dois domínios que fornecem a maior parte da `` incompatibilidade de impedância '' que faz com que algumas pessoas considerem a ORM o 'Vietnã da ciência da computação' .)

Para aplicativos transacionais, ou seja, você faz uma solicitação, obtém alguns objetos, os percorre para obter alguns dados e renderizá-los em uma página da Web, o imposto sobre o desempenho é pequeno e, em muitos casos, o ORM pode ser mais rápido porque armazenará em cache objetos visto antes, isso teria consultado o banco de dados várias vezes.

Para aplicativos com muitos relatórios ou que lidam com um grande número de linhas de banco de dados por solicitação, o imposto ORM é muito mais pesado e o cache que eles fazem se transforma em um grande fardo inútil de consumir memória. Nesse caso, o mapeamento SQL simples (LinQ ou iBatis) ou consultas SQL codificadas manualmente em um DAL fino é o caminho a percorrer.

Descobri que, para qualquer aplicativo em larga escala, você se encontrará usando as duas abordagens. (ORM para CRUD e SQL / DAL simples para geração de relatórios).


Você poderia definir 'grande número de linhas do banco de dados por solicitação'? Por favor :)
Mosselman

Então, posso integrar o JPA ao IBatis, por exemplo? E fazê-los funcionar na mesma transação?
Jaime Hablutzel

2
Outra consideração que ninguém parece discutir é a administração básica do estado. Toda essa pilha de estruturas (JSF, JPA, etc) é baseada nos métodos get / set dos beans Java. Esta é uma tonelada de clichê para todas as tabelas, para todas as colunas e ... aqui está o verdadeiro antipadrão: apenas para expor todos os campos como se fossem públicos. Com efeito, ter um método get / set nos campos de um objeto / tabela / linha está muito perto de violar cada inquilino de ocultação e encapsulamento de informações. Por fim, de volta à administração do estado ... onde está a opção de imutabilidade? Objetos de meio conjunto podem ou devem ser permitidos? Nenhuma opção com a maioria.
Darrell Teague

2
Eu gostaria de aprimorar e concordar particularmente com uma declaração chave nesta resposta. "Para aplicativos que lidam com um grande número de linhas do banco de dados por solicitação, o imposto ORM é muito mais pesado". O ORM é bom apenas para desenvolvedores e manutenção, porque a maioria dos desenvolvedores não é muito boa em SQL, mas se você está realmente falando sobre desempenho, o SQL supera completamente.
Manachi

"a maioria dos desenvolvedores não é muito boa em SQL" ??? Eu diria que a maioria dos desenvolvedores não sabe como usar corretamente o LINQ, o poder das árvores de expressão e os ORMs em geral, a geração de código e muitas outras coisas. Mas não, não tenho base para fazer uma afirmação tão forte.
Adanay Martín

253

Falando como alguém que passou bastante tempo trabalhando com JPA (Java Persistence API, basicamente a API ORM padronizada para Java / J2EE / EJB), que inclui Hibernate, EclipseLink, Toplink, OpenJPA e outros, vou compartilhar alguns dos meus observações.

  1. ORMs não são rápidos. Eles podem ser adequados e, na maioria das vezes, adequados, mas em um ambiente de alto volume e baixa latência, eles são um não-não;
  2. Em linguagens de programação de propósito geral, como Java e C #, você precisa de muita magia para fazê-las funcionar (por exemplo, tecelagem de tempo de carregamento em Java, instrumentação etc.);
  3. Ao usar um ORM, em vez de se afastar do SQL (que parece ser a intenção), você ficará surpreso com quanto tempo gasta aprimorando XML e / ou anotações / atributos para fazer com que seu ORM gere SQL de desempenho;
  4. Para consultas complexas, realmente não há substituto. Como no JPA, existem algumas consultas que simplesmente não são possíveis no SQL bruto e, quando você precisa usar o SQL bruto no JPA, isso não é bom (C # /. Net pelo menos possui tipos dinâmicos - var - o que é muito melhor que uma matriz de objetos);
  5. Existem muitas "dicas" ao usar ORMs. Isso inclui comportamento não intencional ou inesperado, o fato de que você precisa desenvolver a capacidade de fazer atualizações SQL no seu banco de dados (usando refresh () no JPA ou métodos semelhantes, porque o JPA, por padrão, armazena em cache tudo, para não capturar um banco de dados direto atualização - executar atualizações diretas do SQL é uma atividade comum de suporte à produção);
  6. A incompatibilidade objeto-relacional sempre causará problemas. Com qualquer problema desse tipo, há uma troca entre complexidade e completude da abstração. Às vezes, senti que o JPA foi longe demais e atingi uma lei real de retornos decrescentes, onde a complexidade não era justificada pela abstração.

Há outro problema que requer um pouco mais de explicação.

O modelo tradicional de um aplicativo da Web é ter uma camada de persistência e uma camada de apresentação (possivelmente com serviços ou outras camadas intermediárias, mas essas são as duas importantes para esta discussão). Os ORMs forçam uma visão rígida da camada de persistência até a camada de apresentação (ou seja, suas entidades).

Uma das críticas de mais métodos SQL brutos é que você acaba com todos esses VOs (objetos de valor) ou DTOs (objetos de transferência de dados) que são usados ​​por apenas uma consulta. Isso é apresentado como uma vantagem dos ORMs, porque você se livra disso.

O problema é que esses problemas não desaparecem com os ORMs, eles simplesmente passam para a camada de apresentação. Em vez de criar VOs / DTOs para consultas, você cria objetos de apresentação personalizados, geralmente um para cada exibição. Como isso é melhor? IMHO não é.

Eu escrevi sobre isso no ORM ou SQL: já chegamos? .

Minha tecnologia de persistência de escolha (em Java) atualmente é ibatis. É um invólucro bastante fino em torno do SQL que faz mais de 90% do que o JPA pode fazer (ele pode até carregar carregamentos preguiçosos de relacionamentos, embora não esteja bem documentado), mas com muito menos sobrecarga (em termos de complexidade e código real).

Isso surgiu no ano passado em um aplicativo GWT que eu estava escrevendo. Muita tradução do EclipseLink para objetos de apresentação na implementação do serviço. Se estivéssemos usando o ibatis, seria muito mais simples criar os objetos apropriados com o ibatis e passá-los para cima e para baixo na pilha. Alguns puristas podem argumentar que isso é Bad ™. Talvez sim (em teoria), mas eu lhe digo: isso levaria a um código mais simples, uma pilha mais simples e mais produtividade.


2
Fui inspirado a postar outra pergunta (embora seja wiki da comunidade) apenas para coletar recursos sobre coisas como esta. Em relação ao último parágrafo: eu gosto de simplicidade. Provavelmente demais.
hydrapheetz

3
O iBATIS é ótimo, mas talvez você queira experimentar o jOOQ: jooq.sourceforge.net . Seu foco principal é precisamente ficar perto do SQL pelos 6 motivos mencionados.
Lukas Eder

5
+1 para o ponto 3. Muitos acham que o uso do ORM o impede de ter um entendimento completo do SQL. O problema é que, uma vez que você possa / aprenda a fazer ginástica com SQL, provavelmente se verá se afastando do ORM ... muito rapidamente.
Ryan Fernandes

4
Então, agora é o final de 2013 e, como todos sabemos, nada pode ser mais enganador do que "fatos antigos" - então posso perguntar se seus pontos ainda são os mesmos? Caso contrário, seria ótimo se você pudesse escrever um post no blog / atualizar sua resposta de acordo.
Dominik

3
var não produz um tipo dinâmico no .NET, variáveis ​​com a palavra-chave dinâmica são tipos dinâmicos no .NET. var ainda está digitando estática. Veja stackoverflow.com/questions/961581/…
Fazi

45

Eu digo SQL simples para R EADS, ORM para CUD .

Sempre me preocupo com desempenho, principalmente em aplicativos da Web, mas também em manutenção e legibilidade do código. Para resolver esses problemas, escrevi o SqlBuilder .


1
O que é CUD? Não consigo encontrar a definição.
Kimchi Man

27
@KimchiMan CRUD sem o R.
Max Toro

3
CUD - Criar, atualizar, excluir.
Combine

14

ORM não é apenas portabilidade (o que é meio difícil de alcançar, mesmo com ORMs). O que ele oferece é basicamente uma camada de abstração em um armazenamento persistente, quando uma ferramenta ORM o libera de escrever consultas SQL padrão (selecionadas por PK ou por predicados, inserções, atualizações e exclusões) e permite que você se concentre no domínio do problema.


3
Eu estava pensando em algo mais próximo da portabilidade entre os tipos de banco de dados. Não devo postar perguntas tarde da noite.
hydrapheetz

1
Era exatamente o que eu estava dizendo: mesmo os cenários mais básicos podem estar sujeitos a erros em diferentes DBMSes - por exemplo, manipulação diferente de NULLs.
Anton Gogolev 30/01/09

Um ORM fornece uma camada de abstração sobre os relacionamentos entre objetos, mas não há grande vantagem com relação às consultas padrão mencionadas. Em um aplicativo JDBC, você pode gravar esses tipos de consultas com uma pequena quantidade de código em uma superclasse abstrata ou classe de utilitário. Não é necessário repetir o padrão para cada nova tabela.
Kevin Stembridge

11

Qualquer design respeitável precisará de alguma abstração para o banco de dados, apenas para lidar com a incompatibilidade de impedância. Mas o primeiro passo mais simples (e adequado para a maioria dos casos) que eu esperaria seria um DAL, não um ORM pesado. Suas únicas opções não são as que estão no fim do espectro.


EDIT em resposta a um comentário solicitando que eu descreva como eu distingo DAL de ORM:

Um DAL é o que você escreve, talvez começando de uma classe que simplesmente encapsula uma tabela e mapeia seus campos para propriedades. Um ORM é um código que você não escreve ou mecanismos de abstração deduzidos de outras propriedades do esquema dbms, principalmente PKs e FKs. (É aqui que você descobre se as abstrações automáticas começam a vazar ou não. Prefiro informá-las intencionalmente, mas essa pode ser apenas minha preferência pessoal).


2
Onde você desenha a linha entre o que é um DAL e o que é um ORM?
caos

4
Então, se você é o autor de um ORM, seu ORM se transforma automaticamente em um DAL? :)
Bombe

DAL = camada de persistência e ORM é uma ferramenta que você usa dentro do seu DAL para executar operações CRUD no armazenamento de dados.
Vahid Ghadiri

7

Toda ferramenta tem seu objetivo e visão. Eu criei o http://www.jooq.org/ exatamente para atender às suas necessidades, embora o iBatis seja provavelmente uma boa solução para você também.

O jOOQ possui recursos ORM básicos, mas se concentra principalmente nas coisas que eu acho que a maioria dos desenvolvedores mais precisam, ao tentar encontrar o melhor ORM para suas necessidades:

  • geração de código
  • ligação variável (isso é uma dor no JDBC)
  • Abstração de sintaxe SQL (para evitar erros de sintaxe)

Mas muitas vezes eles vão longe demais e fornecem tanta abstração que você não pensaria que eles estão rodando contra um RDBMS. Por outro lado, você escolheu um RDBMS precisamente porque

  • é uma fonte de dados robusta
  • O SQL pode fazer muitas coisas boas e de alto desempenho (seleções aninhadas, uniões, junções complexas etc.). Frequentemente, os ORMs não podem fazer essas coisas.
  • você pode lidar com transações e sessões sozinho
  • você tem UDT e procedimentos armazenados

O jOOQ aborda exatamente esses pontos. Ele terá um desempenho tão bom quanto o JDBC, mas sem a dor.


6

O dilema de usar ou não uma estrutura é bastante comum no cenário de desenvolvimento de software moderno.

O que é importante entender é que toda estrutura ou abordagem tem seus prós e contras - por exemplo, em nossa experiência, descobrimos que o ORM é útil ao lidar com transações, por exemplo, operações de inserção / atualização / exclusão - mas quando se trata de buscar dados com informações complexas. Como resultado, torna-se importante avaliar o desempenho e a eficácia da ferramenta ORM.

Também é importante entender que não é obrigatório selecionar uma estrutura ou uma abordagem e implementar tudo nela. O que queremos dizer com isso é que podemos ter uma mistura de ORM e linguagem de consulta nativa. Muitas estruturas ORM fornecem pontos de extensão para plugins no SQL nativo. Deveríamos tentar não usar demais uma estrutura ou uma abordagem. Podemos combinar certas estruturas ou abordagens e fornecer uma solução apropriada.

Você pode usar o ORM quando se trata de inserção, atualização, exclusão, controle de versão com alto nível de simultaneidade e pode usar o SQL nativo para geração de relatórios e listagem longa


3
Por que um ORM é melhor para alta simultaneidade?
precisa saber é o seguinte

6

A chave que fez meu ORM realmente voar foi a geração de código. Concordo que a rota ORM não é a mais rápida, em termos de desempenho do código. Mas quando você tem uma equipe de médio a grande porte, o banco de dados está mudando rapidamente. A capacidade de regenerar classes e mapeamentos do banco de dados como parte do processo de construção é algo brilhante de se ver, especialmente quando você usa o IC. Portanto, seu código pode não ser o mais rápido, mas sua codificação será - eu sei o que eu aceitaria na maioria dos projetos.

Minha recomendação é desenvolver usando um ORM enquanto o esquema ainda estiver fluido, usar perfis para encontrar gargalos e ajustar as áreas que precisam dele usando o SQL bruto.

Outro pensamento, o cache embutido no Hibernate geralmente pode fazer grandes melhorias de desempenho se usado da maneira correta. Não é mais necessário voltar ao banco de dados para ler os dados de referência.


2
Absolutamente uma questão de gosto pessoal. Para mim, a geração de código é uma falha.
dkretz

5
Leia o segundo parágrafo .... talvez completude também é útil
MrTelly

A geração de código é a única maneira de executar determinadas tarefas mais rapidamente. Como todas as ferramentas, ela pode ser poderosa ou levar a um desastre. Tecnicamente, todas as linguagens estão produzindo outros tipos de código.
Banjocat

4

Não existe uma solução 'uma ferramenta serve para todos', e isso também é verdade para a pergunta 'devo usar um ou / m ou não? '

Eu diria: se você tiver que escrever uma aplicação / ferramenta que seja muito focada em "dados", sem muita outra lógica, usaria o SQL simples, pois o SQL é a linguagem específica de domínio para esse tipo de aplicativo.

Por outro lado, se eu escrevesse um aplicativo comercial / corporativo que contenha muita lógica de 'domínio', escreveria um modelo de classe rica que poderia expressar esse domínio no código. Nesse caso, um mapeador OR / M pode ser muito útil para fazer isso com êxito, pois exige muito código de encanamento de suas mãos.


"Não existe solução 'uma ferramenta serve para todos'" ... bem, deveria haver.
Rushino 21/10

1

Um dos aplicativos que desenvolvi foi um bot de IRC escrito em python. Os módulos que ele usa são executados em threads separados, mas eu não descobri uma maneira de lidar com o encadeamento ao usar o sqlite. Porém, isso pode ser melhor para uma pergunta separada.

Eu realmente deveria ter reformulado tanto o título quanto a pergunta real. Eu nunca usei um DAL antes, em qualquer idioma.


4
Bem, sou da opinião de que você deveria. O SQL bruto em todo o lugar é bastante abominável.
caos

Bem, sim. Há um software de fórum que eu corro de tempos em tempos que tem toneladas de mysql_query () e mysql_result () por todo o lugar. Está nozes.
hydrapheetz

O que é essa coisa de "app" de que você fala?
Zoran Pavlovic

É engraçado que essa pergunta tenha sido feita em um aplicativo irc bot e tenha se tornado o que era (um guia muito útil)! Um aplicativo irc bot está em uma extremidade da escala e um aplicativo que possui mais de 50 a 100 tabelas com junções complexas e milhões de linhas de dados com mais de 20 desenvolvedores trabalhando nele está no outro extremo da escala. Ouso dizer que, quando se trata de um final de escala 'irc bot app', isso pouco importa.
Manachi

1

Use um ORM que funcione como SQL, mas forneça verificações em tempo de compilação e digite segurança. Como o meu favorito: Data Knowledge Objects (divulgação: eu escrevi)

Por exemplo:

for (Bug bug : Bug.ALL.limit(100)) {
  int id = bug.getId();
  String title = bug.getTitle();
  System.out.println(id +" "+ title);
}

Totalmente streaming. Fácil de configurar (sem mapeamentos para definir - lê seus esquemas existentes). Suporta junções, transações, consultas internas, agregação, etc. Praticamente tudo o que você pode fazer no SQL. E foi comprovado a partir de conjuntos de dados gigantes (séries temporais financeiras) até triviais (Android).


Seu IDE também pode fornecer essas verificações estáticas diretamente (a IDEA conhece a estrutura do banco de dados há muito tempo, quando você diz onde está o banco de dados / onde estão os arquivos DDL, para que ele possa fazer verificações de tipo / verificações de relação / etc em suas consultas / procedimentos SQL / o que for )
Xenos

isso é útil. ele pode fazer isso como parte de uma etapa de compilação / IC? como ele classifica sql vs outras strings? ele pode lidar com manipulação de strings ou apenas constantes de strings?
Keredson 22/05/19

Eu vou ser bloqueado pelo abBlock, mas o IntelliJ analisa o SQL como qualquer outro idioma jetbrains.com/datagrip/features para que você possa integrá-lo ao CI / CD / build (talvez pedindo à equipe do IJ para isolar o código de análise do SQL? Talvez o Sonar já esteja tem esse analisador). A análise traz o tipo de dados para que você possa adicionar verificações (fiz isso com um plug-in personalizado) ou verificações como "as colunas JOIN têm um índice FK?"? etc. Estes seriam improvments arrumado para inspeções SQL do IJ nativa
Xenos

1

Sei que essa pergunta é muito antiga, mas pensei em postar uma resposta caso alguém se deparasse com ela como eu. ORMs percorreram um longo caminho. Alguns deles realmente oferecem o melhor dos dois mundos: tornar o desenvolvimento mais produtivo e manter o desempenho.

Dê uma olhada no SQL Data ( http://sqldata.codeplex.com ). É um ORM muito leve para c # que cobre todas as bases.

Para sua informação, sou o autor do SQL Data.


1

Eu gostaria de adicionar minha voz ao coro de respostas que dizem "Há um meio termo!".

Para um programador de aplicativos, o SQL é uma mistura de coisas que você pode querer controlar e coisas que você quase certamente não quer ser incomodado em controlar.

O que eu sempre quis é uma camada (chame DAL, ORM ou micro-ORM, não me importo com qual) que se encarregará das decisões completamente previsíveis (como soletrar palavras-chave SQL, para onde vão os parênteses, quando inventar aliases de coluna, quais colunas criar para uma classe que contém dois carros alegóricos e um int ...), enquanto me deixa encarregado dos aspectos de alto nível do SQL, ou seja, como organizar JOINs, cálculos no lado do servidor, DISTINCTs, GROUP BYs, subconsultas escalares, etc.

Então, eu escrevi algo que faz isso: http://quince-lib.com/

É para C ++: não sei se essa é a linguagem que você está usando, mas, mesmo assim, pode ser interessante ver como isso pode parecer um "meio termo".

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.