shopkeeper
table contient les champs suivants:
id (bigint),amount (numeric(19,2)),createddate (timestamp)
Disons que j'ai le tableau ci-dessus. Je veux obtenir les enregistrements d'hier et générer un rapport en imprimant le montant en cents.
Une façon de faire est d'effectuer des calculs dans mon application java et d'exécuter une requête simple
Date previousDate ;// $1 calculate in application
Date todayDate;// $2 calculate in application
select amount where createddate between $1 and $2
puis parcourez les enregistrements et convertissez le montant en cents dans mon application java et générez le rapport
Une autre méthode consiste à effectuer des calculs dans la requête SQL elle-même:
select cast(amount * 100 as int) as "Cents"
from shopkeeper where createddate between date_trunc('day', now()) - interval '1 day' and date_trunc('day', now())
puis parcourez les enregistrements et générez le rapport
D'une certaine manière, tout mon traitement est effectué dans l'application java et une simple requête est déclenchée. Dans les autres cas, toutes les conversions et calculs sont effectués dans une requête SQL.
Le cas d'utilisation ci-dessus n'est qu'un exemple, dans un scénario réel, une table peut avoir de nombreuses colonnes qui nécessitent un traitement du même type.
Pouvez-vous me dire quelle approche est la meilleure en termes de performances et d'autres aspects et pourquoi?
la source
Réponses:
Cela dépend de nombreux facteurs - mais surtout:
Comme toujours, si vous faites apporter les données à l'application serveur, ce qui réduit les colonnes et les lignes seront à votre avantage. S'assurer que la requête est réglée et correctement indexée aidera les deux scénarios.
Re votre note:
Faire une boucle dans les enregistrements est presque toujours la mauvaise chose à faire en SQL - l'écriture d'une opération basée sur un ensemble est préférable.
En règle générale , je préfère réduire au minimum le travail de la base de données "stocker ces données, récupérer ces données" - cependant, il existe toujours des exemples de scénarios où une requête élégante sur le serveur peut économiser beaucoup de bande passante.
Considérez également: si cela coûte cher en calcul, peut-il être mis en cache quelque part?
Si vous voulez un "ce qui est mieux" précis ; codez-le dans les deux sens et comparez-le (en notant qu'un premier brouillon de l'un ou l'autre n'est probablement pas réglé à 100%). Mais tenez compte de l'utilisation typique à cela: si, en réalité, il est appelé 5 fois (séparément) à la fois, alors simulez cela: ne comparez pas juste un seul "1 de ceux-ci contre 1 de ceux-ci".
la source
Permettez-moi d'utiliser une métaphore: si vous voulez acheter un collier en or à Paris, l'orfèvre pourrait s'asseoir au Cap ou à Paris, c'est une question de compétence et de goût. Mais vous n'expédiez jamais des tonnes de minerai d'or d'Afrique du Sud vers la France pour cela. Le minerai est traité sur le site minier (ou du moins dans la zone générale), seul l'or est expédié. La même chose devrait être vraie pour les applications et les bases de données.
En ce qui concerne PostgreSQL , vous pouvez faire presque tout sur le serveur, de manière assez efficace. Le SGBDR excelle dans les requêtes complexes. Pour les besoins de procédure, vous pouvez choisir parmi une variété de langages de script côté serveur : tcl, python, perl et bien d'autres. Cependant, j'utilise principalement PL / pgSQL .
Le pire des cas serait d'aller à plusieurs reprises sur le serveur pour chaque ligne d'un ensemble plus grand. (Ce serait comme expédier une tonne de minerai à la fois.)
Deuxièmement , si vous envoyez une cascade de requêtes, chacune dépendant de la précédente, alors que tout cela peut être fait en une seule requête ou procédure sur le serveur. (C'est comme expédier l'or et chacun des bijoux avec un navire séparé, séquentiellement.)
Les allers-retours entre l'application et le serveur sont coûteux. Pour serveur et client. Essayez de réduire cela, et vous gagnerez - ergo: utilisez des procédures côté serveur et / ou SQL sophistiqué si nécessaire.
Nous venons de terminer un projet où nous avons intégré presque toutes les requêtes complexes dans les fonctions Postgres. L'application transmet les paramètres et obtient les ensembles de données dont elle a besoin. Rapide, propre, simple (pour le développeur de l'application), E / S réduites au minimum ... un collier brillant à faible empreinte carbone.
la source
Dans ce cas, il vaut probablement mieux faire le calcul en SQL car le moteur de base de données est susceptible d'avoir des routines d'arithmétique décimale plus efficaces que Java.
En général, cependant, pour les calculs au niveau des lignes, il n'y a pas beaucoup de différence.
Là où cela fait une différence, c'est:
la source
Il n'y a pas de noir / blanc en ce qui concerne les parties de la logique d'accès aux données qui doivent être exécutées dans SQL et les parties qui doivent être effectuées dans votre application. J'aime la formulation de Mark Gravell , faisant la distinction entre
La puissance et l'expressivité de SQL sont largement sous-estimées. Depuis l'introduction des fonctions de fenêtre , de nombreux calculs non strictement orientés ensemble peuvent être effectués très facilement et élégamment dans la base de données.
Trois règles empiriques doivent toujours être suivies, quelle que soit l'architecture globale de l'application:
D'après mon expérience, avec un DBA décent et des connaissances décentes sur votre base de données décente, vous ne rencontrerez pas très bientôt les limites de votre CPU DB.
Quelques lectures supplémentaires où ces choses sont expliquées:
la source
En général, faites les choses en SQL s'il y a des chances que d'autres modules ou composants dans le même projet ou d'autres projets aient besoin d'obtenir ces résultats. une opération atomique effectuée côté serveur est également meilleure car il vous suffit d'appeler le proc stocké depuis n'importe quel outil de gestion de base de données pour obtenir les valeurs finales sans autre traitement.
Dans certains cas, cela ne s'applique pas mais quand c'est le cas, cela a du sens. aussi en général, la db box a le meilleur matériel et les meilleures performances.
la source
Si vous écrivez sur ORM ou si vous écrivez des applications occasionnelles à faible performance, utilisez le modèle qui simplifie l'application. Si vous écrivez une application haute performance et réfléchissez bien à l'échelle, vous gagnerez en déplaçant le traitement vers les données. Je recommande vivement de déplacer le traitement vers les données.
Pensons à cela en deux étapes: (1) transactions OLTP (petit nombre d'enregistrements). (2) OLAP (longues analyses de nombreux enregistrements).
Dans le cas OLTP, si vous voulez être rapide (10 000 à 100 000 transactions par seconde), vous devez supprimer les conflits de verrouillage, de verrouillage et de verrouillage mort de la base de données. Cela signifie que vous devez éliminer les longues interruptions dans les transactions: les allers-retours du client à la base de données pour déplacer le traitement vers le client sont l'un de ces longs arrêts. Vous ne pouvez pas avoir de transactions de longue durée (pour rendre la lecture / mise à jour atomique) et avoir un débit très élevé.
Re: mise à l'échelle horizontale. Les bases de données modernes sont mises à l'échelle horizontalement. Ces systèmes implémentent déjà la haute disponibilité et la tolérance aux pannes. Tirez parti de cela et essayez de simplifier votre espace d'application.
Regardons OLAP - dans ce cas, il devrait être évident que faire glisser éventuellement des terrabytes de données vers l'application est une idée horrible. Ces systèmes sont conçus spécifiquement pour fonctionner de manière extrêmement efficace contre des données en colonnes compressées et pré-organisées. Les systèmes OLAP modernes évoluent également horizontalement et disposent de planificateurs de requêtes sophistiqués qui dispersent le travail horizontalement (déplacement interne du traitement vers les données).
la source
Que ce soit pour effectuer des calculs en front-end ou en backend est très décidé si nous pouvons déterminer notre objectif dans la mise en œuvre de l'entreprise. À l'époque, le code java peut être plus performant qu'un code SQL à la fois bien écrit ou vice-versa. Mais si vous êtes confus, vous pouvez essayer de déterminer d'abord -
Il y a de nombreux autres aspects auxquels vous pouvez réfléchir avant de décider où placer le code. Une perception est totalement fausse - Tout peut être fait mieux en Java (code d'application) et / ou tout est mieux fait par le db (code sql).
la source
Formez un point de vue sur les performances: il s'agit d'une opération arithmétique très simple qui peut presque certainement être effectuée beaucoup plus rapidement que d'extraire réellement les données des disques qui sous-tendent la base de données. En outre, le calcul des valeurs dans la clause where est susceptible d'être très rapide à tout moment d'exécution. En résumé, le goulot d'étranglement doit être le disque IO, pas le calcul des valeurs.
En ce qui concerne la lisibilité, je pense que si vous utilisez un ORM, vous devriez le faire dans votre environnement de serveur d'application, car l'ORM vous permettra de travailler très facilement avec les données sous-jacentes, en utilisant des opérations basées sur des ensembles. Si vous allez de toute façon écrire du SQL brut, il n'y a rien de mal à faire le calcul là-bas, votre SQL serait également un peu plus beau et plus facile à lire s'il est formaté correctement.
la source
Fondamentalement, la «performance» n'est pas définie.
Celui qui compte le plus pour moi est le temps des développeurs.
Écrivez la requête SQL. Si c'est trop lent ou si la base de données devient un goulot d'étranglement, alors reconsidérez. À ce moment-là, vous serez en mesure de comparer les deux approches et de prendre votre décision en fonction de données réelles pertinentes pour votre configuration (matériel et quelle que soit la pile sur laquelle vous vous trouvez).
la source
Je ne pense pas que les différences de performances puissent être raisonnées sans exemples et références spécifiques, mais j'ai une autre idée:
Que pouvez-vous mieux entretenir? Par exemple, vous souhaiterez peut-être basculer votre frontal de Java vers Flash, ou HTML5, ou C ++, ou autre chose. Un grand nombre de programmes ont subi un tel changement, ou existent même dans plusieurs langues pour commencer, car ils doivent fonctionner sur plusieurs appareils.
Même si vous avez une couche intermédiaire appropriée (d'après l'exemple donné, il semble que ce n'est pas le cas), cette couche pourrait changer et JBoss pourrait devenir Ruby / Rails.
D'un autre côté, il est peu probable que vous remplaciez le backend SQL par quelque chose qui n'est pas une base de données relationnelle avec SQL et même si vous le faites, vous devrez de toute façon réécrire le front-end à partir de zéro, donc le point est sans objet.
Mon idée est que si vous effectuez des calculs dans la base de données, il sera beaucoup plus facile d'écrire une deuxième couche frontale ou intermédiaire plus tard, car vous n'avez pas à tout réimplémenter. Dans la pratique cependant, je pense que «où puis-je faire cela avec un code que les gens comprendront» est le facteur le plus important.
la source
Pour simplifier la réponse, il faudrait se pencher sur l'équilibrage de charge. Vous voulez placer la charge là où vous avez le plus de capacité (si cela a du sens). Dans la plupart des systèmes, c'est le serveur SQL qui devient rapidement un goulot d'étranglement, donc la réponse est probablement que vous ne voulez pas que SQL fasse une once de travail de plus que nécessaire.
Dans la plupart des architectures, ce sont également les serveurs SQL qui constituent le cœur du système et les systèmes extérieurs qui sont ajoutés.
Mais les calculs ci-dessus sont si triviaux qu'à moins que vous ne poussiez votre système à la limite, le meilleur endroit pour le placer est où vous voulez le mettre. Si les calculs n'étaient pas triviaux, comme le calcul de sin / cos / tan pour, par exemple, un calcul de distance, l'effort pourrait devenir non trivial et nécessiter une planification et des tests minutieux.
la source
Les autres réponses à cette question sont intéressantes. Étonnamment, personne n'a répondu à votre question. Vous vous demandez:
Plus d'informations: Pour la première question, vous voulez être sûr que l'agrégation des fractions fonctionne sans erreurs d'arrondi. Je pense que le numérique 19,2 est raisonnable pour l'argent et dans le second cas, les nombres entiers sont OK. Utiliser un flotteur pour de l'argent est faux pour cette raison.
Pour la deuxième question, j'aime avoir un contrôle total en tant que programmeur sur la date considérée comme «maintenant». Il peut être difficile d'écrire des tests unitaires automatiques lors de l'utilisation de fonctions comme now (). En outre, lorsque vous avez un script de transaction plus long, il peut être bon de définir une variable égale à now () et d'utiliser la variable de sorte que toute la logique utilise exactement la même valeur.
la source
Permettez-moi de prendre un exemple concret pour répondre à cette question
J'avais besoin de calculer une moyenne mobile pondérée sur mes données ohlc, j'ai environ 134000 bougies avec un symbole pour chacune pour le faire
Quel est le meilleur?
Exigences
Pour vous donner quelques encouragements, voici la version Python pour faire une moyenne mobile pondérée
WMA fait par code
WMA via SQL
Croyez-le ou non, la requête s'exécute plus rapidement que la version Pure Python de faire une MOYENNE DE MOUVEMENT PONDÉRÉE !!! Je suis allé étape par étape dans l'écriture de cette requête alors accrochez-vous et vous ferez très bien
La vitesse
0,42141127300055814 secondes Python
0,23801879299935536 secondes SQL
J'ai 134000 faux enregistrements OHLC dans ma base de données répartis sur 1000 actions, c'est donc un exemple où SQL peut surpasser votre serveur d'applications
la source