Vous utilisez un ORM ou un SQL simple? [fermé]

245

Pour certaines des applications que j'ai développées (puis j'ai oublié), j'ai écrit du SQL simple, principalement pour MySQL. Bien que j'aie utilisé des ORM en python comme SQLAlchemy , je n'y suis pas resté longtemps. Habituellement, c'était la documentation ou la complexité (de mon point de vue) qui me retenait.

Je le vois comme ceci: utilisez un ORM pour la portabilité, du SQL simple si cela ne va utiliser qu'un seul type de base de données. Je suis vraiment à la recherche de conseils pour savoir quand utiliser un ORM ou SQL lors du développement d'une application qui a besoin d'un support de base de données.

En y réfléchissant, il serait bien préférable d'utiliser simplement un wrapper léger pour gérer les incohérences de la base de données par rapport à l'utilisation d'un ORM.

hydrapheetz
la source
Standardisation, sécurité, maintenabilité, abstraction de la langue, SEC, etc.
Ben
Les performances avec ORM peuvent être proches de SQL, cela dépend si vous l'utilisez correctement et avec des paramètres corrects ... Voir ho pour rendre EF6.x 5x plus rapide: linkedin.com/pulse/…
baHI
Pour l'architecture ORM et comment faire (à éviter), voici mon autre lien: linkedin.com/pulse/…
baHI
Le mappage relationnel-objet (ORM) est déjà très populaire dans de nombreux langages de programmation et l'une des meilleures alternatives pour SQL. Je me suis inspiré du style de chaînage des méthodes pour créer du CQL pour mon projet TRIADB. healis.eu/triadb/#latest-release
Athanassios
2
Il est stupide que cette question soit close.
Mitch Wheat

Réponses:

169

Les ORM ont de belles fonctionnalités. Ils peuvent gérer une grande partie du travail consistant à copier des colonnes de base de données dans des champs d'objet. Ils gèrent généralement la conversion des types de date et d'heure de la langue vers le type de base de données approprié. Ils gèrent généralement les relations un-à-plusieurs de manière assez élégante également en instanciant des objets imbriqués. J'ai trouvé que si vous concevez votre base de données en gardant à l'esprit les forces et les faiblesses de l'ORM, cela économise beaucoup de travail pour obtenir des données dans et hors de la base de données. (Vous voudrez savoir comment il gère le polymorphisme et les relations plusieurs-à-plusieurs si vous avez besoin de les cartographier. Ce sont ces deux domaines qui fournissent la plupart du «décalage d'impédance» qui fait d'ORM le «Vietnam de l'informatique». .)

Pour les applications qui sont transactionnelles, c'est-à-dire que vous faites une demande, obtenez des objets, parcourez-les pour obtenir des données et les rendre sur une page Web, la taxe sur les performances est faible, et dans de nombreux cas ORM peut être plus rapide car il mettra en cache les objets c'est vu auparavant, qui autrement aurait interrogé la base de données plusieurs fois.

Pour les applications qui génèrent des rapports volumineux ou qui traitent un grand nombre de lignes de base de données par demande, la taxe ORM est beaucoup plus lourde et la mise en cache qu'elles font se transforme en une lourde charge de stockage de mémoire inutile. Dans ce cas, un mappage SQL simple (LinQ ou iBatis) ou des requêtes SQL codées à la main dans un DAL léger est la solution.

J'ai trouvé que pour toute application à grande échelle, vous vous retrouverez à utiliser les deux approches. (ORM pour CRUD simple et SQL / DAL léger pour les rapports).

Cameron Pope
la source
Pourriez-vous définir «un grand nombre de lignes de base de données par demande»? S'il vous plaît :)
Mosselman
Puis-je intégrer JPA avec IBatis par exemple ?? ET les faire fonctionner dans la même transaction?
Jaime Hablutzel
2
Une autre considération que personne ne semble discuter est la gestion de base de l'État. Cette pile complète de frameworks (JSF, JPA, etc.) est basée sur les méthodes get / set des beans Java. C'est une tonne de passe-partout pour chaque table, pour chaque colonne et ... voici le véritable anti-modèle: juste pour exposer chaque champ comme s'il était public. En effet, avoir une méthode get / set sur des champs dans un objet / table / ligne est très proche de violer chaque locataire de masquage et d'encapsulation d'informations. Enfin, revenons à la gestion de l'État ... où est l'option d'immuabilité? Les objets semi-fixes peuvent-ils ou doivent-ils être autorisés? Aucune option avec la plupart.
Darrell Teague
2
Je voudrais affiner et en particulier être d'accord sur une déclaration clé dans cette réponse. "Pour les applications qui traitent un grand nombre de lignes de base de données par demande, la taxe ORM est beaucoup plus lourde". ORM n'est bon que pour les développeurs et la maintenance, car la plupart des développeurs ne sont pas très bons en SQL, mais si vous parlez réellement de performances, SQL l'emporte complètement.
Manachi
"la plupart des développeurs ne sont pas très bons en SQL" ??? Je dirais que la plupart des développeurs ne savent pas comment utiliser correctement LINQ, la puissance des arborescences d'expression et les ORM en général, la génération de code et bien d'autres choses. Mais non, je n'ai aucune base pour faire une déclaration aussi forte.
Adanay Martín
253

Parlant comme quelqu'un qui a passé pas mal de temps à travailler avec JPA (Java Persistence API, essentiellement l'API ORM normalisée pour Java / J2EE / EJB), qui comprend Hibernate, EclipseLink, Toplink, OpenJPA et d'autres, je vais partager certaines de mes observations.

  1. Les ORM ne sont pas rapides. Ils peuvent être adéquats et la plupart du temps adéquats, c'est bien, mais dans un environnement à faible latence et à volume élevé, ce n'est pas le cas;
  2. Dans les langages de programmation à usage général comme Java et C #, vous avez besoin de beaucoup de magie pour les faire fonctionner (par exemple, tissage de temps de chargement en Java, instrumentation, etc.);
  3. Lorsque vous utilisez un ORM, plutôt que de vous éloigner de SQL (ce qui semble être l'intention), vous serez étonné du temps que vous passerez à peaufiner XML et / ou des annotations / attributs pour que votre ORM génère du SQL performant;
  4. Pour les requêtes complexes, il n'y a vraiment aucun substitut. Comme dans JPA, il y a des requêtes qui ne sont tout simplement pas possibles qui sont en SQL brut et quand vous devez utiliser du SQL brut en JPA ce n'est pas joli (C # /. Net a au moins des types dynamiques - var - ce qui est beaucoup plus agréable qu’un tableau Object);
  5. Il y a énormément de "pièges" lors de l'utilisation des ORM. Cela inclut un comportement inattendu ou inattendu, le fait que vous devez intégrer la capacité d'effectuer des mises à jour SQL dans votre base de données (en utilisant refresh () dans JPA ou des méthodes similaires car JPA par défaut met tout en cache pour ne pas intercepter une base de données directe mise à jour - l'exécution de mises à jour SQL directes est une activité courante de support à la production);
  6. Le décalage objet-relationnel va toujours causer des problèmes. Avec un tel problème, il existe un compromis entre la complexité et l'exhaustivité de l'abstraction. Parfois, je sentais que JPA allait trop loin et frappait une véritable loi de rendements décroissants où la complexité n'était pas justifiée par l'abstraction.

Il y a un autre problème qui nécessite un peu plus d'explications.

Le modèle traditionnel pour une application Web est d'avoir une couche de persistance et une couche de présentation (éventuellement avec un service ou d'autres couches entre les deux mais ce sont les deux importantes pour cette discussion). Les ORM forcent une vue rigide de votre couche de persistance jusqu'à la couche de présentation (c'est-à-dire vos entités).

L'une des critiques des méthodes SQL plus brutes est que vous vous retrouvez avec tous ces VO (objets de valeur) ou DTO (objets de transfert de données) qui sont utilisés par une seule requête. Ceci est présenté comme un avantage des ORM parce que vous vous en débarrassez.

Le problème est que ces problèmes ne disparaissent pas avec les ORM, ils se déplacent simplement vers la couche de présentation. Au lieu de créer des VO / DTO pour les requêtes, vous créez des objets de présentation personnalisés, généralement un pour chaque vue. Comment est-ce mieux? À mon humble avis, ce n'est pas le cas.

J'ai écrit à ce sujet dans ORM ou SQL: en sommes-nous encore là? .

Ma technologie de persistance de choix (en Java) de nos jours est ibatis. C'est un wrapper assez mince autour de SQL qui fait 90% + de ce que JPA peut faire (il peut même faire du chargement paresseux des relations bien que ce ne soit pas bien documenté) mais avec beaucoup moins de frais généraux (en termes de complexité et de code réel).

Cela est apparu l'année dernière dans une application GWT que j'écrivais. Beaucoup de traduction d'EclipseLink vers des objets de présentation dans l'implémentation du service. Si nous utilisions ibatis, il aurait été beaucoup plus simple de créer les objets appropriés avec ibatis, puis de les passer tout le long de la pile. Certains puristes pourraient soutenir que c'est Bad ™. Peut-être que oui (en théorie) mais je vous dis quoi: cela aurait conduit à du code plus simple, une pile plus simple et plus de productivité.

cletus
la source
2
J'ai été inspiré pour poster une autre question (bien que wiki communautaire) juste pour collecter des ressources sur des choses comme ça. Concernant le dernier paragraphe: j'aime la simplicité. Probablement trop.
hydrapheetz
3
iBATIS est génial, mais vous voudrez peut-être essayer jOOQ: jooq.sourceforge.net . Son objectif principal est précisément de rester proche de SQL pour les 6 raisons que vous avez mentionnées.
Lukas Eder
5
+1 pour le point 3. Beaucoup pensent que l'utilisation d'ORM vous soulage d'avoir une compréhension approfondie de SQL. Le fait est qu'une fois que vous pouvez / apprendre à faire de la gymnastique avec SQL, vous vous éloignerez probablement de l'ORM ... très rapidement.
Ryan Fernandes
4
Donc, maintenant c'est la fin de 2013 et comme nous le savons tous, rien ne pourrait être plus trompeur que les "vieux faits" - alors puis-je vous demander si vos points sont toujours les mêmes? Sinon, ce serait bien si vous pouviez écrire un article de blog / mettre à jour votre réponse en conséquence.
Dominik
3
var ne produit pas de type dynamique dans .NET, les variables avec le mot-clé dynamic sont des types dynamiques dans .NET. var est toujours du typage statique. Voir stackoverflow.com/questions/961581/…
Fazi
45

Je dis SQL simple pour R eads, ORM pour CUD .

Les performances me préoccupent toujours, en particulier dans les applications Web, mais aussi la maintenabilité et la lisibilité du code. Pour résoudre ces problèmes, j'ai écrit SqlBuilder .

Max Toro
la source
1
Qu'est-ce que CUD? Je ne trouve pas la définition.
Kimchi Man
27
@KimchiMan CRUD sans le R.
Max Toro
3
CUD - Créer, mettre à jour, supprimer.
Combinez le
14

ORM n'est pas seulement la portabilité (ce qui est un peu difficile à réaliser même avec des ORM, d'ailleurs). Ce qu'il vous donne est essentiellement une couche d'abstraction sur un magasin persistant, lorsqu'un outil ORM vous libère de l'écriture de requêtes SQL standard (sélection par PK ou par prédicats, insertions, mises à jour et suppressions) et vous permet de vous concentrer sur le domaine problématique.

Anton Gogolev
la source
3
Je pensais à quelque chose de plus proche de la portabilité entre les versions de base de données. Je ne devrais pas poster de questions tard dans la nuit.
hydrapheetz
1
C'est exactement ce que je disais: même les scénarios les plus élémentaires peuvent potentiellement être sujets à des erreurs dans différents SGBD - par exemple, une gestion différente des NULL.
Anton Gogolev le
Un ORM vous donne une couche d'abstraction sur les relations entre les objets, mais il n'y a pas de grand avantage en ce qui concerne les requêtes standard que vous mentionnez. Dans une application JDBC, vous pouvez écrire ces types de requêtes avec une petite quantité de code dans une superclasse abstraite ou une classe utilitaire. Il n'est pas nécessaire de répéter le passe-partout pour chaque nouvelle table.
Kevin Stembridge
11

Toute conception respectable nécessitera une certaine abstraction pour la base de données, juste pour gérer le décalage d'impédance. Mais la première étape la plus simple (et adéquate pour la plupart des cas) que j'attendrais serait un DAL, pas un ORM lourd. Vos seules options ne sont pas celles situées aux extrémités du spectre.


EDIT en réponse à un commentaire me demandant de décrire comment je distingue DAL de ORM:

Un DAL est ce que vous écrivez vous-même, peut-être à partir d'une classe qui encapsule simplement une table et mappe ses champs aux propriétés. Un ORM est du code que vous n'écrivez pas ou des mécanismes d'abstraction déduits d'autres propriétés de votre schéma dbms, principalement des PK et des FK. (C'est là que vous découvrez si les abstractions automatiques commencent à fuir ou non. Je préfère les informer intentionnellement, mais cela peut être ma préférence personnelle).

dkretz
la source
2
Où tracez-vous la frontière entre ce qui est un DAL et ce qui est un ORM?
chaos
4
Donc, si vous êtes l'auteur d'un ORM, votre ORM redevient automatiquement un DAL? :)
Bombe
DAL = couche de persistance et ORM est un outil que vous utilisez dans votre DAL pour effectuer des opérations CRUD dans le magasin de données.
Vahid Ghadiri
7

Chaque outil a sa raison d'être et sa vision. J'ai créé http://www.jooq.org/ exactement pour répondre à vos besoins, mais iBatis est probablement aussi une bonne solution pour vous.

jOOQ a des fonctionnalités ORM de base, mais il se concentre principalement sur les choses dont je suppose que la plupart des développeurs ont le plus besoin, lorsqu'ils essaient de trouver le meilleur ORM pour leurs besoins:

  • génération de code
  • liaison variable (c'est un problème dans JDBC)
  • Abstraction de syntaxe SQL (pour éviter les erreurs de syntaxe)

Mais souvent, ils vont trop loin et fournissent tellement d'abstraction que vous ne penseriez pas qu'ils fonctionnent contre un SGBDR. D'un autre côté, vous avez choisi un SGBDR précisément parce que

  • c'est une source de données robuste
  • SQL peut faire beaucoup de choses bonnes et performantes (sélections imbriquées, unions, jointures complexes, etc.). Souvent, les ORM ne peuvent pas faire ces choses.
  • vous pouvez gérer vous-même les transactions et les sessions
  • vous avez des procédures UDT et stockées

jOOQ aborde exactement ces points. Il fonctionnera aussi bien que JDBC, mais sans douleur.

Lukas Eder
la source
6

Le dilemme d'utiliser ou non un framework est assez courant dans les scénarios de développement de logiciels modernes.

Ce qui est important à comprendre, c'est que chaque cadre ou approche a ses avantages et ses inconvénients - par exemple, selon notre expérience, nous avons constaté que l'ORM est utile lors du traitement des transactions, c'est-à-dire des opérations d'insertion / mise à jour / suppression - mais lorsqu'il s'agit de récupérer des données avec des résultats, il devient important d'évaluer les performances et l'efficacité de l'outil ORM.

Il est également important de comprendre qu'il n'est pas obligatoire de sélectionner un cadre ou une approche et de tout mettre en œuvre. Ce que nous entendons par là, c'est que nous pouvons avoir un mélange d'ORM et de langage de requête natif. De nombreux frameworks ORM donnent des points d'extension au plugin en SQL natif. Nous devons essayer de ne pas trop utiliser un cadre ou une approche. Nous pouvons combiner certains cadres ou approches et proposer une solution appropriée.

Vous pouvez utiliser ORM en ce qui concerne l'insertion, la mise à jour, la suppression, le contrôle de version avec un niveau élevé de concurrence et vous pouvez utiliser Native SQL pour la génération de rapports et la liste longue

Rutesh Makhijani
la source
3
Pourquoi un ORM est-il meilleur pour une concurrence élevée?
user359996
6

La clé qui a vraiment fait voler mon utilisation ORM était la génération de code. Je suis d'accord que la route ORM n'est pas la plus rapide, en termes de performances de code. Mais lorsque vous avez une équipe moyenne à grande, la base de données modifie rapidement la capacité de régénérer les classes et les mappages à partir de la base de données dans le cadre du processus de génération est quelque chose de brillant à voir, surtout lorsque vous utilisez CI. Donc, votre code n'est peut-être pas le plus rapide, mais votre codage sera - je sais que je prendrais dans la plupart des projets.

Ma recommandation est de développer à l'aide d'un ORM alors que le schéma est encore fluide, d'utiliser le profilage pour trouver des goulots d'étranglement, puis de régler les zones qui en ont besoin en utilisant SQL brut.

Une autre pensée, la mise en cache intégrée à Hibernate peut souvent améliorer considérablement les performances si elle est utilisée de la bonne manière. Plus besoin de revenir à la base de données pour lire les données de référence.

MrTelly
la source
2
Absolument une question de goût personnel. Pour moi, la génération de code est un défaut.
dkretz
5
Lire le deuxième paragraphe .... peut-être que l'exhaustivité est également utile
MrTelly
La génération de code est le seul moyen d'accomplir certaines tâches plus rapidement. Comme tous les outils, il peut être puissant ou conduire à une catastrophe. Techniquement, tous les langages produisent d'autres types de code.
Banjocat
4

Il n'y a pas de solution «un seul outil pour tous», et cela est également vrai pour la question «dois-je utiliser un ou / m ou non? '.

Je dirais: si vous devez écrire une application / un outil très axé sur les données, sans beaucoup d'autre logique, alors j'utiliserais du SQL simple, car SQL est le langage spécifique au domaine pour ce type d'applications.

D'un autre côté, si je devais écrire une application d'entreprise / entreprise qui contient beaucoup de logique de «domaine», j'écrirais alors un modèle de classe riche qui pourrait exprimer ce domaine en code. Dans ce cas, un mappeur OR / M peut être très utile pour le faire avec succès, car il vous enlève beaucoup de code de plomberie.

Frederik Gheysels
la source
"Il n'y a pas de solution" un seul outil pour tous "".
Rushino
1

L'une des applications que j'ai développées était un bot IRC écrit en python. Les modules qu'il utilise s'exécutent dans des threads séparés, mais je n'ai pas trouvé de moyen de gérer le threading lors de l'utilisation de sqlite. Cependant, cela pourrait être mieux pour une question distincte.

J'aurais vraiment dû reformuler le titre et la vraie question. Je n'ai jamais utilisé de DAL auparavant, dans aucune langue.

hydrapheetz
la source
4
Eh bien, je suis d'avis que vous devriez. Le SQL brut partout est assez abominable.
chaos
Ben ouais. Il y a un logiciel de forum que je pirate de temps en temps qui a des tonnes de mysql_query () et mysql_result () partout. C'est fou.
hydrapheetz
Quelle est cette chose "app" dont vous parlez?
Zoran Pavlovic
C'est drôle que cette question ait été posée sur une application irc bot et soit devenue ce qu'elle était (un guide très utile)! Une application de bot irc se trouve à une extrémité de l'échelle, et une application qui a 50-100 + tables avec des jointures complexes et des millions de lignes de données avec plus de 20 développeurs qui y travaillent est à l'autre extrémité de l'échelle. J'ose dire quand il s'agit d'une extrémité de l'échelle de l'application irc bot, cela n'a guère d'importance.
Manachi
1

Utilisez un ORM qui fonctionne comme SQL, mais qui fournit des vérifications à la compilation et une sécurité de type. Comme mon préféré: Data Knowledge Objects (divulgation: je l'ai écrit)

Par exemple:

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

Streaming complet. Facile à configurer (pas de mappage à définir - lit vos schémas existants). Prend en charge les jointures, les transactions, les requêtes internes, l'agrégation, etc. Pratiquement tout ce que vous pouvez faire en SQL. Et a été prouvé à partir d'ensembles de données géants (séries temporelles financières) jusqu'à trivial (Android).

Keredson
la source
Votre IDE peut également fournir ces vérifications statiques directement (IDEA connaît la structure de la base de données tant que vous lui dites où se trouve la base de données / où se trouvent les fichiers DDL, il peut donc effectuer des vérifications de type / vérifications de relations / etc. dans vos requêtes / procédures SQL / quoi que ce soit )
Xenos
c'est utile. peut-il le faire dans le cadre d'une étape de build / CI? comment classe-t-il sql par rapport aux autres chaînes? peut-il gérer la manipulation de chaînes, ou seulement les constantes de chaînes?
keredson
Je serai bloqué par abBlock, mais IntelliJ analyse SQL comme tout autre langage jetbrains.com/datagrip/features afin que l'on puisse l'intégrer à CI / CD / build (peut-être en demandant à l'équipe IJ d'isoler le code d'analyse SQL? Peut-être que Sonar est déjà a un tel analyseur). L'analyse apporte le type de données afin que vous puissiez y ajouter des vérifications (je l'ai fait avec un plugin personnalisé), ou des vérifications comme "les colonnes JOIN ont-elles un index FK?" etc. Ce seraient des améliorations soignées des inspections SQL natives d'IJ
Xenos
1

Je sais que cette question est très ancienne, mais je pensais que je posterais une réponse au cas où quelqu'un la rencontrerait comme moi. Les ORM ont parcouru un long chemin. Certains d'entre eux vous offrent en fait le meilleur des deux mondes: rendre le développement plus productif et maintenir les performances.

Jetez un œil aux données SQL ( http://sqldata.codeplex.com ). C'est un ORM très léger pour c # qui couvre toutes les bases.

Pour info, je suis l'auteur de SQL Data.

tjscience
la source
1

Je voudrais ajouter ma voix au chœur de réponses qui disent "Il y a un juste milieu!".

Pour un programmeur d'applications, SQL est un mélange de choses que vous voudrez peut-être contrôler et de choses que vous ne voudrez certainement pas être gêné de contrôler.

Ce que j'ai toujours voulu, c'est une couche (appelez-la DAL, ORM ou micro-ORM, ça ne me dérange pas) qui prendra en charge les décisions complètement prévisibles (comment épeler les mots clés SQL, où vont les parenthèses, quand d'inventer des alias de colonnes, quelles colonnes créer pour une classe qui contient deux flottants et un int ...), tout en me laissant en charge des aspects de niveau supérieur du SQL, c'est-à-dire comment organiser les JOIN, les calculs côté serveur, DISTINCT, GROUP BY, sous-requêtes scalaires, etc.

J'ai donc écrit quelque chose qui fait ceci: http://quince-lib.com/

C'est pour C ++: je ne sais pas si c'est le langage que vous utilisez, mais il pourrait tout de même être intéressant de voir ce que pourrait être un "terrain d'entente".

slyqualin
la source