Wann ist es besser, die Arbeit in das RDBMS auszulagern, als sie in Code auszuführen?

12

Okay, ich komme damit klar: Ich bin ein besserer Programmierer als ich es von Datenbanken her kenne, und ich frage mich, wo die Überlegungen zu "Best Practices" zum Thema "einfache" Berechnungen in der SQL-Abfrage im Vergleich zu "in" liegen der Code, wie dieses MySQL-Beispiel (ich habe ihn nicht geschrieben, ich muss ihn nur warten!) - Dies gibt den Benutzernamen und das Alter des Benutzers ab dem letzten Ereignis zurück.

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
...

Verglichen mit dem "schweren" Heben von Code:

Abfrage:

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."; 

Ich bin mir ziemlich sicher, dass es in einem einfachen Fall wie diesem keinen großen Unterschied machen würde (abgesehen von dem schleichenden Gefühl des Grauens, wenn ich Änderungen an Abfragen wie der ersten vornehmen muss), aber ich denke, es macht klarer, was ich meine. Ich suche.

Vielen Dank!

GeminiDomino
quelle
1
Dies ist eine gute Frage - ich bin auf dasselbe Problem gestoßen.
Michael K
Hier ist ein gutes Beispiel dafür, wann ich es nicht tun soll: calendar.sql (Ja, das ist meine Monstrosität, ja, es war eine schlechte Idee und nein, es ist nicht langsam.)
greyfade
Ihr flippenden Götter ... Ich wette, die MD5 für dieses Ding ist "CthulhuFhtagn"
GeminiDomino

Antworten:

13

Sie möchten aus Leistungsgründen alle satzbasierten Operationen in der Datenbank ausführen. Also Aggregationsfunktionen, Sortierfunktionen, Joins etc.

Diese Altersberechnung würde ich in Code machen. Der einzige Grund, warum ich jemals so etwas in einer Datenbankabfrage tun könnte, ist, dass viele Spalten erforderlich sind, die ich sonst nicht auswählen würde und die tatsächlich ausreichen könnten, um meine Abfrage sinnvoll zu verlangsamen. Die Auswahl einiger ganzzahliger Werte hat keinen wesentlichen Einfluss auf die Leistung. Und selbst wenn es einen moderaten Leistungsunterschied macht, bin ich voreingenommen, diese Logik im Anwendungscode beizubehalten.

Jeremy
quelle
Genau. Code, der zu Anzeigezwecken mit Werten spielt, sollte in Ihrem App-Code enthalten sein.
TehShrike
4

Jeder Fall ist anders

Ist die Logik ...

  • von anderen Kunden benötigt? TROCKEN: in der Datenbank
  • zur Weiterverarbeitung verwendet? zB nach Alter absteigend sortieren: in der Datenbank
  • Benötigen Sie regionale Einstellungen? TT / MM / JJJJ oder MM / TT / JJJJ: im Client
  • oft benutzt? Warum immer wieder berechnen: berechnete und persistierte Spalte in der Datenbank verwenden

In diesem Fall verwende ich möglicherweise eine berechnete und permanente Spalte in der Datenbank

Es könnte schlimmer sein: Sie könnten dies in der Datenbank haben:

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

Grundsätzlich sollten Sie sich zwei Dinge ansehen: CPU-Auslastung und Netzwerkverkehr. Sie sollten keine enormen Antworten generieren, sie über das Netzwerk übertragen und dann im Frontend zusammenfassen, da die Datenbank dies viel besser kann.

Für die Datenmanipulation ist es ein handels von. Wenn die Datenbank die gleiche Menge an CPU-Zyklen für Ihren Frontend-Code ausgibt (vorausgesetzt, die übertragene Datenmenge ist ungefähr gleich), spielt es keine Rolle, wo. Dann machen Sie es dort, wo Sie die größte Programmierkenntnis haben. Häufig kann man mit einer sorgfältigen Auswahl einen sehr langen Weg zurücklegen, was sehr nützlich sein kann.


quelle
1

Sie haben eines erwähnt: Fachgebiet. Möglicherweise ist die Struktur der Datenbank nicht zu umfangreich, sodass Sie einen Teil der Logikentwicklung auf ein Teammitglied verlagern, das stärker auf die Datenbank ausgerichtet ist. Das ist vielleicht nicht ideal, aber wenn Sie auf die Zeit drängen ...

Die Datenbankhardware verfügt über erheblich mehr Ressourcen als andere Server, und Sie können dies nicht ändern. Dies gilt möglicherweise nicht für diese spezielle Situation, muss jedoch möglicherweise berücksichtigt werden.

Es gibt andere Anwendungen, für die möglicherweise eine Logik außerhalb Ihres Codes erforderlich ist. Einige Berichterstellungstools können möglicherweise keinen Webdienst oder keine API verwenden. Sie könnten die Logik duplizieren oder wenn Sie der Meinung sind, dass die Anforderungen abweichen könnten.

JeffO
quelle
"Die Datenbankhardware verfügt über erheblich mehr Ressourcen als andere Server, und Sie können dies nicht ändern." - wie? Woher kommen diese beiden Aussagen?
Peter Boughton
Ich denke, Jeff könnte über eigenständige Datenbankserver sprechen. Ich hätte wahrscheinlich spezifizieren sollen, dass ich hauptsächlich an LA [MP] P-Setups arbeite.
GeminiDomino
1
Ein LAMP-Setup ist kein Grund, keinen eigenständigen Datenbankserver zu haben, und ein eigenständiger Datenbankserver ist auch keine Garantie dafür, dass mehr Ressourcen zur Verfügung stehen oder dass dies nicht geändert werden kann.
Peter Boughton
Hrm. Ich bin mir dann nicht sicher.
GeminiDomino
@Peter Boughton, DB und App auf demselben Server haben eine um eine Größenordnung kürzere Zeit für die Schnittstellenverbindung und größere E / A-Werte. Es gibt echte Gründe, diese beiden zusammen zu lokalisieren.
Jé Queue
0

Ich irre mich immer darum, so viel Arbeit in die DB zu stecken. Ihre obige Syntax könnte auch mit DB-Funktionen geschrieben werden, die IMO eine sehr saubere Lösung wären.

Jé Queue
quelle