Quand est-il préférable de décharger le travail vers le SGBDR plutôt que de le faire en code?

12

D'accord, je vais y faire face: je suis un meilleur codeur que je ne le suis dans les bases de données, et je me demande où se trouvent les réflexions sur les "meilleures pratiques" sur le sujet de faire des calculs "simples" dans la requête SQL par rapport à le code, comme cet exemple MySQL (je ne l'ai pas écrit, je dois juste le maintenir!) - Cela retourne le nom d'utilisateur et l'âge des utilisateurs au dernier événement.

SELECT u.username as user, 
       IF ((DAY(max(e.date)) - DAY(u.DOB)) < 0 ,   
       TRUNCATE(((((YEAR(max(e.date))*12)+MONTH(max(e.date)))
       -((YEAR(u.DOB)*12)+MONTH(u.DOB)))-1)/12, 0),  
       TRUNCATE((((YEAR(max(e.date))*12)+MONTH(max(e.date))) -            
       ((YEAR(u.DOB)*12)+MONTH(u.DOB)))/12, 0)) AS age   
FROM users as u
JOIN events as e ON u.id = e.uid
...

Par rapport à faire le levage "lourd" dans le code:

Requete:

SELECT u.username, u.DOB as dob, e.event_date as edate
FROM users as u
JOIN events as e ON u.id = e.uid

code:

function ageAsOfDate($birth, $aod)
{    //expects dates in mysql Y-m-d format...
     list($by,$bm,$bd) = explode('-',$birth);
     list($ay,$am,$ad) = explode('-',$aod);

     //Insert Calculations here 
     ...
     return $Dy; //Difference in years
}

echo "Hey! ". $row['user'] ." was ". ageAsOfDate($row['dob'], $row['edate']) . " when we last saw him."; 

Je suis assez sûr que dans un cas simple comme celui-ci, cela ne ferait pas beaucoup de différence (à part le sentiment d'horreur rampant quand je dois apporter des modifications à des requêtes comme la première), mais je pense que cela rend plus clair ce que je '' cherche m.

Merci!

GeminiDomino
la source
1
C'est une bonne question - j'ai rencontré le même problème.
Michael K
Voici un bon exemple de quand ne pas le faire: calendar.sql (Oui, c'est ma monstruosité, oui, c'était une mauvaise idée, et non, ce n'est pas lent.)
greyfade
Vous renversez les dieux ... Je parie que le MD5 pour cette chose se révèle être "CthulhuFhtagn"
GeminiDomino

Réponses:

13

Vous souhaitez effectuer toutes les opérations basées sur des ensembles dans la base de données pour des raisons de performances. Donc fonctions d'agrégation, fonctions de tri, jointures etc.

Ce calcul d'âge, je le ferais en code. La seule raison pour laquelle je pourrais faire quelque chose comme ça dans une requête de base de données, c'est si cela nécessitait beaucoup de colonnes que je ne sélectionnerais pas autrement qui pourraient en fait constituer suffisamment de données pour ralentir significativement ma requête. La sélection de quelques valeurs entières ne fera pas de différence significative de performances. Et même si cela fait une différence de performance modérée, je serai partisan de conserver cette logique dans le code de l'application.

Jeremy
la source
Je suis d'accord. Le code qui tripote les valeurs à des fins d'affichage doit être dans le code de votre application.
TehShrike
4

Chaque cas est différent

Est la logique ...

  • besoin d'autres clients? SEC: dans la base de données
  • utilisé pour un traitement ultérieur? ex: tri par âge décroissant: dans la base de données
  • nécessite des paramètres régionaux? jj / mm / aaaa ou mm / jj / aaaa: chez le client
  • utilisé souvent? Pourquoi le calculer encore et encore: utilisez une colonne calculée et persistante dans la base de données

Dans ce cas, je pourrais utiliser une colonne calculée et persistante dans la base de données

Cela pourrait être pire: vous pourriez avoir ceci dans la base de données:

"Hey! ". u.username." was ". <datecalc>. " when we last saw him."
gbn
la source
3

Fondamentalement, vous devez considérer deux choses: l'utilisation du processeur et le trafic réseau. Vous ne devez pas générer de réponses énormes, les transférer sur le réseau, puis résumer dans le frontend, car la base de données peut faire beaucoup mieux.

Pour la manipulation des données, c'est un échange. Si la base de données passe une quantité comparable de cycles de processeur à votre code frontal faisant la même chose - étant donné que la quantité de données transférées est à peu près équivalente), alors peu importe où. Faites-le ensuite là où vous possédez la plus grande expertise en programmation. Souvent, vous pouvez obtenir un TRÈS long chemin avec une sélection minutieuse et cela pourrait être très utile.


la source
1

Vous en avez mentionné un: domaine d'expertise. Peut-être que la structure de la base de données n'est pas trop intensive, vous décidez donc de décharger une partie du développement logique à un membre de l'équipe plus centré sur la base de données. Ce n'est peut-être pas idéal, mais si vous manquez de temps ...

Le matériel de la base de données a beaucoup plus de ressources que les autres serveurs et vous ne pouvez pas changer cela. Cela peut ne pas s'appliquer à cette situation spécifique, mais peut devoir être pris en considération.

Il existe d'autres applications qui peuvent avoir besoin de la logique en dehors de votre code. Certains outils de rédaction de rapports peuvent ne pas être en mesure d'utiliser un service Web ou une API. Vous pouvez dupliquer la logique ou si vous pensez que les exigences peuvent diverger.

JeffO
la source
"Le matériel de la base de données a beaucoup plus de ressources que les autres serveurs et vous ne pouvez pas changer cela." - hein? D'où viennent ces deux déclarations?
Peter Boughton
Je pense que Jeff pourrait parler de serveurs de base de données autonomes. J'aurais probablement dû spécifier que je travaille principalement sur les configurations LA [MP] P.
GeminiDomino
1
Une configuration LAMP n'est pas une raison pour ne pas avoir de serveur de base de données autonome, et un serveur de base de données autonome n'est pas une garantie de plus de ressources ni de ne pas pouvoir changer cela.
Peter Boughton
Hrm. Pas sûr alors.
GeminiDomino
@Peter Boughton, DB et app sur le même serveur ont un ordre de grandeur moins de temps pour la connexion d'interface et des amplitudes IO supérieures tout au long, il y a de vraies raisons de localiser ces deux ensemble.
Jé Queue
0

Je me trompe toujours en mettant autant de traitement sur la DB. Votre syntaxe ci-dessus pourrait également être écrite avec des fonctions DB qui seraient IMO une solution très propre.

Jé Queue
la source