C'est une idée que j'ai entendue répéter dans une poignée d'endroits. Certains reconnaissent plus ou moins qu’une fois que l’on essaie de résoudre un problème uniquement en SQL dépasse un certain niveau de complexité, vous devriez effectivement le traiter en code.
La logique derrière l’idée est que, dans la grande majorité des cas, le moteur de base de données sera plus efficace pour trouver le moyen le plus efficace d’accomplir votre tâche que vous ne le pourriez en code. Surtout lorsqu'il s'agit de subordonner les résultats aux résultats des opérations effectuées sur les données. Sans doute avec les moteurs modernes, JIT'ing + la mise en cache de la version compilée de votre requête aurait du sens en surface.
La question est de savoir si l'exploitation de votre moteur de base de données de cette manière est intrinsèquement une mauvaise pratique de conception (et pourquoi). Les lignes deviennent plus floues quand toute la logique existe dans la base de données et que vous la frappez simplement via un ORM.
la source
Réponses:
En termes simples:
Ce sont des choses que SQL est fait pour faire et, croyez-le ou non, j'ai vu le faire en code:
Faire ces choses au lieu de faire appel à SQL ou au SGBDR conduit à écrire des tonnes de code sans valeur ajoutée , ce qui signifie plus de code à déboguer et à maintenir. Et cela suppose dangereusement que la base de données ne sera accessible que via l'application.
la source
Je reformulerais que de « Ne jamais faire dans le code ce que SQL Server peut faire pour vous bien ».
Des choses comme la manipulation de chaînes, le travail sur les regex et ce que je ne ferais pas dans SQL Server (sauf SQL CLR).
Ce qui précède a tendance à parler de choses telles que les jointures, les opérations définies et les requêtes. L’intention sous-jacente est de déléguer une grande partie de la charge lourde à SQL Server (ce qui est bien) et de réduire autant que possible le nombre d’IO (pour que SQL puisse faire les jointures et filtrer avec une
WHERE
clause, renvoyant beaucoup ensemble de données plus petit qu'autrement).la source
La clé de la réponse est que vous devez rechercher le SQL qui fait quelque chose de bien, par opposition à simplement faire quelque chose, pour vous. SQL est un langage incroyablement puissant. Couplé à des fonctions intégrées, il peut potentiellement faire beaucoup de choses. Cependant, le fait que vous puissiez faire quelque chose en SQL ne devrait pas être une excuse pour le faire réellement en SQL.
Mon critère spécifique pour prendre une décision est de regarder la quantité de données que vous récupérez et le nombre d'allers-retours: si vous pouvez réduire la quantité de données en envoyant une tâche au serveur, sans augmenter le nombre d'allers-retours. voyages, la tâche appartient au serveur; Si la quantité de données reste la même ou augmente sans baisse simultanée du nombre d'allers-retours, la tâche appartient à votre code.
Considérez ces exemples:
la source
WHERE
clause.En résumé , il serait correct de dire que: "N'effectuez jamais d' opérations spécifiques à une base de données dans votre base de code" car elles sont mieux traitées dans votre base de données.
Regardez l'exemple des opérations de la base d'ensemble . Comme vous le savez peut-être, les SGBDR sont conçus pour gérer des opérations courantes de stockage et de manipulation de données.
De plus, le choix du projet de base de données joue un rôle important . Avoir un SGBDR (MS SQL, Oracle, etc.) est différent des bases de données NoSQL telles que RavenDB.
la source
En règle générale, votre base de données dispose de plus d'informations que votre application et peut effectuer des opérations de données communes plus efficacement. Votre base de données conserve des index, par exemple, tandis que votre application devrait indexer les résultats de la recherche à la volée. Donc, toutes choses étant égales par ailleurs, votre charge de travail globale peut être réduite en transférant le travail vers la base de données plutôt que vers l'application.
Mais à mesure que votre produit évolue, il devient généralement plus facile de faire évoluer votre application que de faire évoluer votre base de données. Dans les installations de grande taille, il n’est pas rare de voir les serveurs d’applications plus nombreux que les serveurs de base de données par un facteur de 10 à 1 ou plus. L'ajout de serveurs d'applications consiste souvent à cloner un serveur existant sur un nouveau matériel. L'ajout de nouveaux serveurs de base de données, en revanche, est considérablement plus difficile dans la plupart des cas.
Donc, à ce stade, le mantra devient protéger la base de données . Il se trouve qu'en mettant en cache les résultats
memcached
ou en mettant en file d'attente les mises à jour dans un journal côté application, ou en récupérant les données une fois et en calculant les statistiques dans votre application, vous pouvez réduire considérablement la charge de travail de votre base de données, ce qui vous évite d'avoir à recourir à une configuration de cluster de base de données encore plus compliquée et fragile.la source
Je pense que ce serait une mauvaise conception de ne pas utiliser la base de données pour les objets auxquels elle est destinée. Je n'ai jamais vu de base de données où les règles étaient appliquées en dehors de la base de données et qui contenaient de bonnes données. Et j'ai examiné des centaines de bases de données.
Donc, les choses qui doivent être faites dans une base de données:
Audit (l'audit uniquement sur les applications ne suivra pas toutes les modifications apportées à la base de données et ne vaut donc rien).
Les contraintes d’intégrité des données, y compris les valeurs par défaut, les contraintes de clé étrangère et les règles qui doivent toujours être appliquées à toutes les données. Toutes les données ne sont pas toujours modifiées ou insérées via une application. Il existe des correctifs de données ponctuels, en particulier pour les grands ensembles de données, qui ne sont pas pratiques pour créer un enregistrement à la fois (veuillez mettre à jour ces 100 000 enregistrements dont le statut 1 a été mal défini. être 2 en raison d’un bogue de code d’application ou mettre à jour tous les enregistrements du client A au client B car la société B a acheté la société A), ainsi que des importations de données et d’autres applications susceptibles de toucher à la même base de données.
Filtrage des clauses JOINS et where (pour réduire le nombre d'enregistrements envoyés sur le réseau)
la source
La base de données est exactement cela; la couche de données de votre application. Son travail consiste à fournir à votre application les données demandées et à stocker les données qui lui sont fournies. Votre application est l'endroit où placer le code qui fonctionne réellement avec les données; l'afficher, le valider, etc.
Bien que le sentiment dans la ligne de titre soit admirable et précis à un point (le filtrage, la projection, le regroupement, etc. devraient dans la plupart des cas être laissés à la DB), une définition du "bien" pourrait ordre. Les tâches que SQL Server peut exécuter avec un niveau de performance élevé sont nombreuses, mais les tâches que vous pouvez démontrerque SQL Server exécute correctement de manière isolée et répétable sont très rares. SQL Management Studio est un excellent IDE de base de données (surtout compte tenu des autres options avec lesquelles j'ai travaillé, tel que TOAD), mais il a ses limites, en premier lieu, à peu près tout ce pour quoi vous l'utilisez (ou tout code de procédure que vous exécutez dans la base de données ci-dessous) est par définition un "effet secondaire" (modification de l’état situé en dehors du domaine de l’espace mémoire de votre processus). En outre, le code procédural dans SQL Server n’est qu’à présent, avec les derniers outils de développement intégré et outils, pouvant être mesuré comme le code géré peut utiliser des métriques de couverture et une analyse de chemin (vous pouvez ainsi démontrer que cette instruction est rencontrée par des tests X , Y et Z, et le test X est conçu pour rendre la condition vraie et exécuter cette moitié pendant que Y et Z exécutent le "else" . Cela suppose que vous disposiez d'un test capable de configurer la base de données avec un état de démarrage particulier, d'exécuter le code de procédure de la base de données par une action quelconque et de valider les résultats attendus.
Tout cela est beaucoup plus difficile et complexe que la solution fournie par la plupart des couches d'accès aux données; supposons que la couche de données (et, en l'occurrence, le DAL) sache comment faire son travail lorsque l'entrée est correcte, puis testez que votre code fournit une entrée correcte. En gardant le code procédural comme les SP et les déclencheurs en dehors de la base de données et en faisant ce type de choses dans le code d'application, ledit code d'application est beaucoup plus facile à exercer.
la source
Les gens ne semblent pas se rendre compte que faire tout votre traitement sur le serveur SQL n’est pas forcément bon, quels que soient les effets sur la qualité du code.
Par exemple, si vous avez besoin de récupérer des données, puis de calculer quelque chose à partir des données, puis de les stocker dans la base de données. Il y a deux choix:
Vous pensez peut-être que la deuxième solution est toujours la plus rapide, mais ce n'est certainement pas vrai. J'ignore même si SQL convient mal au problème (c'est-à-dire la manipulation de regex et de chaînes). Supposons que vous avez SQL CLR ou quelque chose de similaire pour avoir un langage puissant dans la base de données même. S'il faut 1 seconde pour effectuer un aller-retour et obtenir les données, 1 seconde pour les stocker, puis 10 secondes pour effectuer le calcul. Vous le faites mal si vous faites tout dans la base de données.
Bien sûr, vous rase 2 secondes. Cependant, aviez-vous plutôt perdu 100% (au moins) d'un cœur de processeur sur votre serveur de base de données pendant 10 secondes ou plutôt perdu votre temps sur votre serveur Web?
Les serveurs Web sont faciles à mettre à l'échelle, tandis que les bases de données sont extrêmement coûteuses, notamment les bases de données SQL. La plupart du temps, les serveurs Web sont également "sans état" et peuvent être ajoutés et supprimés à volonté, sans configuration supplémentaire autre que l'équilibreur de charge.
Alors, pensez non seulement à gagner 2 secondes sur une opération, mais aussi à l’évolutivité. Pourquoi gaspiller une ressource coûteuse telle que les ressources de serveur de base de données quand vous pouvez utiliser les ressources de serveur Web beaucoup moins chères avec un impact relativement faible sur les performances
la source
J'aime regarder cela comme SQL ne devrait traiter que des données elles-mêmes. Les règles métier qui déterminent l'apparence de la requête peuvent se produire dans le code. La regex ou la validation de l'informaiton devrait être faite en code. SQL devrait être laissé pour simplement rejoindre votre table, interroger vos données, insérer des données propres, etc.
Ce qui est passé dans SQL devrait être des données propres et SQL ne devrait pas vraiment avoir besoin de savoir plus que ce dont il a besoin pour le stocker, le mettre à jour, le supprimer ou le récupérer. J'ai vu beaucoup trop de développeurs vouloir jeter leur logique métier et leur codage en SQL car ils considèrent les données comme leur métier. Découplez votre logique de vos données et vous constaterez que votre code devient plus propre et plus facile à gérer.
Juste mon 0,02 $ cependant.
la source
De manière générale, je conviens que le code doit contrôler la logique métier et que la base de données doit être un hachage sans logique. Mais voici quelques contre points:
Les contraintes principales, les clés étrangères et les contraintes requises (et non nulles) peuvent être appliquées par code. Les contraintes sont la logique métier. Devraient-ils être exclus de la base de données car ils dupliquent ce que le code peut faire?
Est-ce que d'autres parties en dehors de votre contrôle touchent la base de données? Si c'est le cas, avoir des contraintes appliquées près des données est bien. L'accès peut être restreint à un service Web qui implémente la logique, mais cela suppose que vous y étiez "le premier" et que vous ayez le pouvoir d'imposer l'utilisation du service aux autres parties.
Votre ORM effectue-t-il une insertion / mise à jour séparée pour chaque objet? Si tel est le cas, vous aurez de graves problèmes de performances lors du traitement par lots de grands ensembles de données. Définir les opérations est la voie à suivre. Un ORM aura du mal à modéliser avec précision tous les ensembles joints sur lesquels vous pouvez effectuer des opérations.
Considérez-vous une "couche" comme une division physique par serveurs ou une division logique? L'exécution de la logique sur n'importe quel serveur pourrait théoriquement toujours tomber sous sa couche logique. Vous pouvez organiser la scission en compilant dans différentes DLL plutôt que de scinder les serveurs exclusivement. Cela peut considérablement augmenter le temps de réponse (mais en sacrifiant beaucoup) tout en maintenant la séparation des problèmes. Une DLL divisée pourrait ensuite être déplacée vers d'autres serveurs sans nouvelle génération afin d'augmenter le débit (au prix du temps de réponse).
la source
L'idiome est plus lié à la conservation des règles métier, aux données, ainsi qu'aux relations (les données et la structure et les relations). Ce n'est pas un guichet unique pour chaque problème, mais cela permet d'éviter des choses comme manuellement compteurs d’enregistrements maintenus, intégrité maintenue manuellement, etc., si ces éléments sont disponibles au niveau de la base de données. Ainsi, si quelqu'un d'autre étend et étend les programmes ou écrit un autre programme qui interagit avec la base de données, ils n'auront pas à trouver comment maintenir l'intégrité de la base de données à partir du code précédent. Le cas d'un compteur d'enregistrement géré manuellement est particulièrement pertinent lorsque quelqu'un d'autre souhaite créer un nouveau programme pour interagir avec la même base de données. Même si le programme nouvellement créé a exactement le bon code pour le compteur, le programme original et le nouveau programme exécuté à peu près au même moment risquent de le corrompre. Il existe même du code qui récupère des enregistrements et vérifie les conditions avant d'écrire un enregistrement nouveau ou mis à jour (sous forme de code ou sous forme de requêtes distinctes), lorsque cela est souvent possible directement dans l'instruction insert ou update. Une corruption de données peut à nouveau résulter. Le moteur de base de données garantit l'atomicité; une mise à jour ou une requête d'insertion avec des conditions est garantie pour n'affecter que les enregistrements respectant les conditions et aucune requête externe ne peut modifier les données à mi-chemin de notre mise à jour. Il existe de nombreuses autres circonstances dans lesquelles le code est utilisé lorsque le moteur de base de données serait mieux utilisé. Tout est question d'intégrité des données et non de performance. s même du code qui récupère des enregistrements et vérifie les conditions avant d'écrire un enregistrement nouveau ou mis à jour (sous forme de code ou sous forme de requêtes distinctes), lorsque cela est possible si cela est souvent possible directement dans l'instruction insert ou update. Une corruption de données peut à nouveau résulter. Le moteur de base de données garantit l'atomicité; une mise à jour ou une requête d'insertion avec des conditions est garantie pour n'affecter que les enregistrements respectant les conditions et aucune requête externe ne peut modifier les données à mi-chemin de notre mise à jour. Il existe de nombreuses autres circonstances dans lesquelles le code est utilisé lorsque le moteur de base de données serait mieux utilisé. Tout est question d'intégrité des données et non de performance. s même du code qui récupère des enregistrements et vérifie les conditions avant d'écrire un enregistrement nouveau ou mis à jour (sous forme de code ou sous forme de requêtes distinctes), lorsque cela est possible si cela est souvent possible directement dans l'instruction insert ou update. Une corruption de données peut à nouveau résulter. Le moteur de base de données garantit l'atomicité; une mise à jour ou une requête d'insertion avec des conditions est garantie pour n'affecter que les enregistrements respectant les conditions et aucune requête externe ne peut modifier les données à mi-chemin de notre mise à jour. Il existe de nombreuses autres circonstances dans lesquelles le code est utilisé lorsque le moteur de base de données serait mieux utilisé. Tout est question d'intégrité des données et non de performance. Le moteur de base de données garantit l'atomicité; une mise à jour ou une requête d'insertion avec des conditions est garantie pour n'affecter que les enregistrements respectant les conditions et aucune requête externe ne peut modifier les données à mi-chemin de notre mise à jour. Il existe de nombreuses autres circonstances dans lesquelles le code est utilisé lorsque le moteur de base de données serait mieux utilisé. Tout est question d'intégrité des données et non de performance. Le moteur de base de données garantit l'atomicité; une mise à jour ou une requête d'insertion avec des conditions est garantie pour n'affecter que les enregistrements respectant les conditions et aucune requête externe ne peut modifier les données à mi-chemin de notre mise à jour. Il existe de nombreuses autres circonstances dans lesquelles le code est utilisé lorsque le moteur de base de données serait mieux utilisé. Tout est question d'intégrité des données et non de performance.
C'est donc un bon idiome de conception ou une règle de base. Aucune quantité de performance ne va aider dans un système avec des données corrompues.
la source
Comme mentionné précédemment, l'objectif est d'envoyer et de recevoir le moins possible de la base de données car les allers-retours sont très coûteux en temps. L'envoi de déclarations SQL à répétition est une perte de temps, en particulier pour les requêtes plus complexes.
L'utilisation de procédures stockées dans la base de données permet aux développeurs d'interagir avec la base de données comme une API, sans se soucier du schéma complexe à l'arrière. Cela réduit également les données envoyées au serveur car seuls le nom et quelques paramètres sont envoyés. Dans ce scénario, la plupart de la logique d'entreprise peut toujours figurer dans le code, mais pas sous la forme de code SQL. Le code préparerait essentiellement ce qui doit être envoyé ou demandé à la base de données.
la source
Il y a quelques points à retenir:
la source
Utilisez l'outil le plus approprié pour le travail. Pour l'intégrité des données, il s'agit souvent de la base de données. Pour les règles métier avancées, il s'agit d'un système à base de règles tel que JBoss Drools. Pour la visualisation des données, il s'agirait d'un cadre de reporting. etc.
Si vous rencontrez des problèmes de performances, vous devez ensuite rechercher si des données peuvent être mises en cache ou si une implémentation dans la base de données serait plus rapide. En général, le coût d'achat de serveurs supplémentaires ou d'une puissance de cloud supplémentaire sera nettement inférieur au coût de maintenance supplémentaire et à l'impact de bogues supplémentaires.
la source