« ORM or not ORM » :
Faut-il les utiliser ou continuer d'écrire simplement des requêtes SQL ?

Le , par imikado

0PARTAGES

3  0 
Et vous les ORM ?
Avec l’arrivée des frameworks php, nous avons appris à évoluer entre ces nouveaux acronymes: MVC, DAO, DRY et ORM
Mais qu’est-ce qu’un ORM ?
Un ORM (Object Relation Mapping) est un ensemble de librairies qui vous permettent d’interagir avec vos données via des objets.
La plupart des frameworks respectant le design MVC* intègrent leurs propres ORM plus ou moins performants.
note: pour les exemples de syntaxes d’ORM j’utiliserai l’ORM du mkFramework.

*MVC: Model View Controller (séparation de la couche modèle de l’affichage et du contrôleur)

Un ORM pourquoi faire ?
Pourquoi utiliser un ORM plutôt que d’écrire simplement des requêtes SQL dans pdo ?
Si vous voulez coder propre, vous allez dans un premier temps écrire toutes vos requêtes dans un fichier php.
Si vous souhaitez organiser un peu mieux, vous allez regrouper les requêtes par table…
Si vous souhaitez éviter de vous répéter, vous aller créer un fichier/une classe pour les éléments récurrents (connexion, requête…) : principe de DRY*
Le fait de faire ceci, vous avez créé un pseudo début d’ORM

*DRY Don’t Repeat Yourself (créer des fonctions/classes pour éviter d’écrire plusieurs fois le même code)

Un des avantages des ORM se situe concernant la manipulation des données.
Prenons un exemple ou dans plusieurs pages vous devez modifier uniquement le titre, l’auteur ou le nombre de vues d’un article.
En pdo simple vous écririez:
Code : Sélectionner tout
1
2
3
‘UPDATE article SET titre=? WHERE id=?’,$titre,$îd 
‘UPDATE article SET auteur=? WHERE id=?’,$auteur,$îd 
‘UPDATE article SET nbVue=nbVue+1 WHERE id=?’,$îd
Avec l’ORM vous n’avez pas besoin d’écrire à l’avance vos différents types de requêtes
Code php : Sélectionner tout
1
2
3
4
5
6
7
8
9
$oArticle=model_Article::getInstance()->findById($id); 
$oArticle->titre=$titre; 
$oArticle->save(); 
//ou 
$oArticle->auteur=$auteur; 
$oArticle->save(); 
//ou 
$oArticle->nbVue=($oArticle->nbVue+1); 
$oArticle->save();
note: vous pouvez, si vous le souhaitez écrire des requêtes update
Exemple:
Code php : Sélectionner tout
1
2
3
4
5
6
class model_article extends abstract_model{ 
() 
public function updateNbVue($id){ 
$this->execute(‘UPDATE article SET nbVue=nbVue+1 WHERE id=?’,$id); 
} 
}
Les avantages sont multiples:
  • Organiser vos requêtes
  • Gagner du temps à l’écriture
  • Bénéficier des avantages du design MVC*


Tous les ORMs n’offrent pas les mêmes performances
Pour argumenter un post dans un topic sur ce même site, j’avais à l’époque procédé au benchmark suivant:
100 000 enregistrements en base de données mysql, et l’affichage de ces lignes dans un tableau HTML.
5 types différents:
- PHP simple en utilisant pdo
- une application en Zend Framework (version 1.11.12)
- une application en Yii (version yii-1.1.14)
- une application en MkFramework (méthode findMany() )
- une application en MkFramework en utilisant la récupération rapide (méthode findManySimple() )

Résultat des courses:
- 0.50s : pdo simple
- 0.58s : MkFramework en utilisant la récupération rapide
- 0.68s : Yii (version yii-1.1.14)
- 1.97s : MkFramework (normal)
- 11.20s : Zend Framework (version 1.11.12):

note : j’ai fait un benchmark sur 100 000 entrées pour avoir un volume assez important pour mettre en évidence les différences de performances, si j’avais fait un findById(4)
Sur un seul enregistrement on a
- 0.007s : pdo simple
- 0.015s : MkFramework en utilisant la récupération rapide
- 0.043s : MkFramework (normal)
- 0.049s : Zend Framework

note 2 pour obtenir de bonnes performances avez yii j’ai écrit les requêtes sans passer par les classes « ORM »
Code php : Sélectionner tout
1
2
3
4
$sql=’SELECT * FROM Article’; 
$connection=Yii::app()->db; // vous devez avoir une connection « db » 
$command=$connection->createCommand($sql); 
$articles=$rows=$command->queryAll();
note 2: j’ai fait un benchmark sur 100 000 entrées pour avoir un volume assez important pour mettre en évidence les différences de performances, si j’avais fait un findById(4)

Les ORMs offrent de la flexibilité
J’ai lu à plusieurs reprise que les ORM étaint lourd, qu’ils retournaient toujours toutes les colonnes même ceux non utilisées, que pour faire une jointure on se retrouvait à récupérer une ligne entière sur les deux tables liés…
Premièrement, vous pouvez choisir de récupérer uniquement certains champs de votre table. Beaucoup d’ORM proposent d’écrire sa requête SQL
Par exemple:

Code php : Sélectionner tout
1
2
3
4
5
6
class model_article extends abstract_model{ 
() 
public function findListAuteurName(){ 
return $this->findMany(‘SELECT auteur.name FROM auteur’); 
} 
}

Idem pour les fameuses jointures, vous avez le choix de récupérer par exemple un objet article puis de lui demander de nous retourner son auteur pour afficher son nom ainsi

Code php : Sélectionner tout
1
2
$oArticle=model_article::getInstance()->findById(4); 
print $oArticle->findAuteur()->nom;

Mais vous pouvez également écrire une méthode qui vous retournera les articles avec leur auteurs

Code php : Sélectionner tout
1
2
3
4
5
6
class model_article extends abstract_model{ 
() 
public function findArticleWithAuteur(){ 
return $this->findOne(‘SELECT article.titre, auteur.name FROM article INNER JOIN auteur ON article.auteur_id=auteur.id WHERE article.id=?’,(int)$id); 
} 
}

Une flexibilité aussi concernant les performances: selon les parties de vos sites vous avez besoin de récupérer plus ou moins d’élements et ceci plus ou moins rapidement.
La encore vous avez le choix: si vous devez récupérer un auteur, ses articles et ceci sans trop regarder les performances vous pouvez utiliser la méthode de récupération d’objets riches findMany/findOne
Si au contraire vous souhaitez afficher un bon nombre d’article d’auteurs, ou autre, vous pouvez utiliser la méthode rapide retournant des objets « simple » findManySimple/findOneSimple

Vous avez le choix

Conclusion
Comme vous avez pu le lire ici, tous les ORM ne sont pas des usines à gaz, ils sont très pratiques et vous permettent dans l’esprit du MVC de bien organiser votre couche modèle.
Les ORM sont une bonne chose que vous codiez une petite application ou une application importante: l’essentiel c’est de penser à long terme (la maintenabilité).
Il sera plus simple pour vous ou un collègue d’intervenir sur votre application avec ORM que sans ORM
Certains ORM sont plus ou moins flexible et performants comme les frameworks, mais ne les mettez pas tous dans le même panier, essayez en plusieurs avant de vous faire un avis.

note: je n’ai pas inclus Symfony 2 (pour tester doctrine) dans le benchmark, car malgré mes efforts d’optimisation de cache, mode production… je n’arrivais pas à passer sous la barre des 23 secondes
Si vous pouvez m’envoyer un exemple d’application affichant ces 100 000 enregistrements en moins de 2 secondes je suis preneur

note2: retrouvez dans mon post d’origine les éléments du benchmark (sauf celui de yii fait ici pour l’occasion)
http://www.developpez.net/forums/d12...u/#post6847792

Le billet: http://blog.developpez.com/ducodeetd...l-les-utiliser

Ci-joint les fichiers logs complets (réalisé via la commande time et wget 10 fois de suite)

Et vous ? utilisez vous un ORM si oui lequel ?
Si non qu'utilisez vous ? pdo ? odbc ? fonction spéciale (mysql_connect, myqli,oci_connect...)

Une erreur dans cette actualité ? Signalez-le nous !

Avatar de rasta tom
Futur Membre du Club https://www.developpez.com
Le 11/09/2013 à 14:30
Dommage que le bench ne compare pas les même choses, ni les bonnes choses !!

D'une avec un ORM c'est vraiment un non sens de récupérer 100 000 objets, l'ORM va récupérer les données depuis la BDD puis "remplir" 100 000 objets correspondants, forcément ça créer une charge supplémentaire très importante par rapport à un pdo classique !! Ce n'est vraiment pas un scénario réaliste donc ca n'apporte pas grand chose pour quelqu'un qui voudrait faire un choix à partir de ces données de test. En général pour ce genre de cas les ORM propose des modes qui permettent de s'affranchir de cette phase de "remplissage" et de gagner beaucoup en perf !

Ensuite pour Yii ne pas utiliser les classes d'ORM ça ne sert juste à rien puisque le but est d'évaluer l'ORM. Pour le test donnée c'est équivalent à du pdo simple avec une légère surcharge pour les classes de connections et d’exécution de la requête. C'est un peu comme si on faisait un bench de framework pour le rendu d'1 fichier html statique

Enfin comme noté par Tsilefy, avec ce bench je peux prendre le meilleur ORM du monde et le mettre dans un framework tout pourri et les résultats seront mauvais alors que peut etre l'ORM en lui même est excellent
3  0 
Avatar de martin.magakian
Futur Membre du Club https://www.developpez.com
Le 11/09/2013 à 18:31
Difficile à dire comme souvent avec ce genre de question.
Il y a les pour et les contre.

L'ORM oui! Mais lorsqu'il s'agit d'une application entreprise. Que les performance ne soit pas impérative. Que le nombre de QPS reste faible.
Quand le temps que me fait gagner l'ORM est supérieur au temps perdu par mes client pour cause d'ORM.

l'ORM, j'adore. C'est magique. Mais j'y vois deux problème major:
- Une logique simple ce traduit souvent pas énormément de requêtes simplissime. ENORMEMENT de requêtes simplissime.
- Cette technique camoufle trop la logique interne. L'abstraction fait gagner un temps précieux. Mais lorsque il faut optimiser un requête ou comprendre un bug, le temps gagner grâce à l'ORM est perdu. On ce retrouve à faire des hack monstrueux.

Les ORM sont trop souvent choisis en espérant avoir quelque chose de simple, de plus rapide à developer sans trop dégrader les performance.
- Simple: Oui, oui, oui !
- Rapide à développer: oui si on n'en fait pas une utilisation exotique.
- performant: non, non, non (ou à grand coup de hack)

Deux axes d'amélioration:
- Utiliser une BDD NoSQL de type document oriented tel que CouchDB ou MongoDB.
En gérant les entités on fait des read/save/update/delete d'une seul coup. Le travail de l'ORM est largement simplifier.

- Faire du ORM semi-manager type "SQL mapping framework". CAD écrire les requêtes SQL et définir un mappaging en objet. Avoir la main sur les requêtes permet d'améliorer les performance et évite les requettes "idiote" des ORM.
Exemple: mybatis (Java), Soma (C#) ...

Martin Magakian
3  0 
Avatar de buxbux
Membre averti https://www.developpez.com
Le 11/09/2013 à 15:18
Certes les ORM ralentissent l’exécution du code, cependant il faut les utiliser a bon escient. C'est a dire dans des projets ou ajouter un niveau d'abstraction a du sens.

Un projet avec plusieurs dizaines d'entités et de relations entre-elles ne se portera que mieux avec un ORM même si ils sont lourd.

Reste ensuite a utiliser les ORM correctement, sinon on se retrouve avec des charge monstrueuses oui. Par contre, bien utilisé on gagne de très nombreuses heures en maintenabilité et évolutivité...
2  0 
Avatar de Gugelhupf
Modérateur https://www.developpez.com
Le 11/09/2013 à 20:00
Il y a plusieurs choses qu'un ORM ne peut pas résoudre contrairement à PDO/ODBC/JDBC : les requêtes de sélection un peu complexe, ou bien les connexions à divers SGBD en même temps par exemple.

Aussi, le but d'un ORM n'est pas d'enregistrer/récupérer 100 000 tuples dans une base. Généralement on se sert de la pagination (ex: récupérer les 20 premiers messages de ce topic).

Cette article n'est malheureusement pas neutre, il n'y a pas de pour et contre concernant les ORM, mais que du pour. Au vu de ces benchmarks, cet article fait un peu pub du framework MkFramework.

Je vous renvoie à un excellent article d'aout 2012 concernant les ORM sur developpez.com.
3  1 
Avatar de tontonnux
Membre expérimenté https://www.developpez.com
Le 11/09/2013 à 17:06
J'utilise Doctrine puisque je travaille avec Symfony.
L'ORM apporte un confort dont j'aurai du mal à me passer dans l'absolue. Maintenant, c'est vrai qu'il peut être à l'origine de certaines lourdeurs. Cependant, mon expérience tend à montrer que ces situations représentent presque toujours des cas dans lequel l'ORM n'est pas aussi indispensable.
Aussi, je pense qu'utiliser un ORM dans un projet objet est une bonne chose, mais il ne faut pas s'abstenir de coupler son usage avec du PDO selon le besoin.

En clair, il n'y a pas de ORM VS PDO, mais une bonne utilisation des deux selon le besoin.
1  0 
Avatar de matios
Nouveau membre du Club https://www.developpez.com
Le 11/09/2013 à 20:43
J'aime le langage SQL ! Donc je n'utilise pas d'ORM car c'est un vrai plaisir de pondre du SQL !!!

Et dire que maintenant, beaucoup de personnes se disant "programmeur" connaissent uniquement "les base"s du langage SQL. Une honte !!
3  2 
Avatar de Gugelhupf
Modérateur https://www.developpez.com
Le 11/09/2013 à 20:57
Vous avez loisir pour écrire vos propres requêtes SQL aussi complexe qu'elles soient : tous les ORM proposent la possibilité d'écrire sa requête SQL.
Je ne sais pas comment c'est avec les autres ORM, mais de souvenir avec Doctrine2 et son DQL, il n'y a pas l'équivalent de l'instruction standard SQL "CASE WHEN", pas de "LIMIT" (qu'on aurait pu utiliser dans une sous-requête par exemple), et pas de fonction équivalent à TO_DATE et TO_CHAR qu'on peut trouver dans PostgreSQL ou Oracle...

Donc même s'il est possible d'écrire sa requête "SQL" avec un ORM, je trouve que ça reste assez limité.
Je n'ai rien contre les ORM, c'est bien sympa pour faire du INSERT|UPDATE|DELETE et les SELECT simples, mais ça n'arrive pas à la cheville du SQL lorsqu'on veut récupérer des données sous une certaine forme.

je fais un benchmark sur 100 000 tuples pour avoir du volume et ainsi mieux mettre en évidence les différences de performances
C'est bien ça le problème, quand je lis le titre de l'article « ORM or not ORM » : faut-il les utiliser ou continuer d'écrire simplement des requêtes SQL ? je ne m'attends pas à une série de benchmark d'ORM mais un débat sur le pour ou contre, et les raisons qui poussent à leur utilisation ou non.
D'ailleurs, faire un benchmark sur un SELECT simple d'une table c'est un peu du pipi de chat, faudrait faire cela avec une requête plus compliqué.
1  0 
Avatar de Tsilefy
Membre émérite https://www.developpez.com
Le 13/09/2013 à 0:07
@ imikado: FIG et ses PSRs est une initiative formidable entre les producteurs de frameworks et librairies pour établir un standard et des interfaces communes permettant d'interchanger ces composants sans difficultés. À mon avis, c'est la plus grand innovation en PHP depuis l'arrivée de PHP 5.2.

Et je préfère largement Symfony2 à 1.4, moins de magie et plus de contrôle :-) Mais c'est vrai, j'ai des vieilles applications en 1.4 et il est hors de question de les migrer, tant qu'elles marchent et qu'il n'y a pas de problèmes de sécurité.
1  0 
Avatar de laffreuxthomas
Membre confirmé https://www.developpez.com
Le 13/09/2013 à 12:07
Au-delà des considérations générales, il existe un impact négatif en PHP sur l'utilisation systématique d'objets. Selon moi cela suffit à changer de perspective par rapport à d'autres langages : les bonnes pratiques en PHP ne sont pas les mêmes que celles en Java. Le cœur de PHP est le tableau PHP. Et ça tombe bien car le SQL est fait pour ramener des tableaux. Alors pour la simplicité et la performance, restons-en à l'essentiel : le couple SQL-tableau PHP.
1  0 
Avatar de imikado
Rédacteur https://www.developpez.com
Le 13/09/2013 à 13:33
Citation Envoyé par Traroth2 Voir le message
Si c'est pour finir par faire du SQL, je ne vois pas l'intérêt de faire du SQL. Je travaille justement en ce moment sur un projet utilisant Hibernate et qui est entièrement fait avec des native queries (du SQL, quoi). Et justement, il s'agit de passer d'Oracle à MySQL, ce qui est bien le seul intérêt d'un ORM à mes yeux. En l'occurrence, je ne comprends pas à quoi sert Hibernate dans le projet. On va devoir valider toutes les requêtes SQL pour être sûr qu'elles marchent avec MySQL. Hibernate ajoute simplement un niveau de complexité supplémentaire dont on se passerait bien, finalement.
L'intérêt de l'ORM :
- organiser les requetes SQL (on groupe les requetes pas table/entité concerné)
- la flexibilité sur la manipulation (on recupere un objet, on met des champs à jour et on sauvegarde)
- on profite des avantages du MVC
- profitez du DRY *

*DRY : Don't Repeat Yourself. Par exemple une chose toute bête: vous souhaitez récupérer tous les articles d'un auteur donné.
Si vous faites du sql pure, vous allez écrire votre requete dans la page d'affichage des articles de l'auteur, et si vous avez besoin à un autre endroit de faire la même chose vous allez devoir recopier ce bout de code
L'avantage avec un ORM c'est ici, dans la classe de l'article vous allez ajouter une fois une requete recuperant les entrées d'un auteur passé en variable.
Vous pourrez l'appeler de n'importe ou à n'importe quel moment, et si pour une raison ou une autre il y a des changements à faire vous modifierez uniquement cette méthode

Citation Envoyé par laffreuxthomas

Une base de données relationnelle est une collection de lignes de données dans des tables et non pas une collection d'objets instanciant des classes.

Un mapping objet sert à naviguer d'objet en objet. Chaque objet est chargé avec l'intégralité d'une ligne d'une table. Et peu importe que telle colonne ne soit pas utilisée par telle partie du programme, l'objet du mapping chargera toujours toutes les colonnes.

Par comparaison, le SQL sert à sélectionner les valeurs des cellules dont on a besoin et uniquement celles-là. Et ça tombe bien car il est rare d'avoir besoin simultanément de toutes les colonnes d'une table dans une même portion du programme.

En SQL nous effectuons des jointures afin de ramener en une requête telle cellule d'une table couplée à telle autre d'une autre table. Alors que dans le même temps un ORM ramène brutalement en deux requêtes séparées deux lignes entières.
Vous pouvez le faire aussi
Dans mes projets il m'arrive d'avoir besoin de joindre N tables.
Prenons par exemple une table lié à une catégorie et un auteur:
Vous avez le choix soit de faire appel à l'objet article et lui demander de vous retourner l'objet catégorie et auteur, soit écrire une methode qui vous retourne un objet article riche contenant exactement les champs demandés
C'est souple un ORM : vous avez le choix
1  0 
Contacter le responsable de la rubrique Accueil

Partenaire : Hébergement Web