Laden...

MySQL Cross Join über drei Tables für ein Update

Erstellt von lazy vor 7 Jahren Letzter Beitrag vor 7 Jahren 3.387 Views
lazy Themenstarter:in
18 Beiträge seit 2012
vor 7 Jahren
MySQL Cross Join über drei Tables für ein Update

verwendetes Datenbanksystem: mysql 5.7

Ich habe 3 Tabellen und möchte einen crossjoin machen.

Tabellen:
player,
garage,
car

Ich möchte vom Spieler das Geld updaten, der mehrere autos in der garage haben kann. Autos haben einen Mietpreis, den ich pro auto vom geld abziehen möchte.

Das Problem: Vom Geld wird immer nur der Mietpreis des ersten Fahrzeugs des jeweiligen Spielers abgezogen

Versucht habe ich das so:


UPDATE player p 
JOIN garage g ON p.id = garage.owner 
JOIN car c ON c.id = garage.car
SET p.money = p.money - c.rentrate, g.lastpaidrent = NOW()
WHERE c.rented = '1' AND TIMESTAMPDIFF(HOUR, c.lastpaidrent, NOW()) >= 24 AND p.money >= c.rentrate

Wie beschrieben, updated er das geld des jeweiligen Spielers zwar, aber immer nur mit der Rate des Autos, das als erstes vom JOIN ausgespuckt wird. Die lastpaidrent wird bei allen einträgen geupdated.

Meine Frage: Kann ich das überhaupt mit einem Cross table update umsetzen (wenn ja, wie?) oder muss ich das über einen Loop abfrühstücken?

5.657 Beiträge seit 2006
vor 7 Jahren

Hi lazy,

warum willst du diese Funktionalität überhaupt mit SQL umsetzen?

Das Ganze ist doch Teil der Anwendungs- bzw. Spielelogik, und gehört daher in die Logikschicht. Siehe dazu auch: [Artikel] Drei-Schichten-Architektur

Weeks of programming can save you hours of planning

T
2.219 Beiträge seit 2008
vor 7 Jahren

@MrSparkle
Stimmt schon, aber wenn man dies über die DB lösen kann, dann sollte man dies auch tun.
Auch ist seine aktuelle Architektur nicht ersichtlich, deshalb ist mir nicht ganz klar ob der Hinweis auf die drei Schichten Architektur ihm weiterhilft.

@MrSparkle
Ich würde, je nachdem wie die Tabellen aufgebaut sind, die Fahrzeuge durchlaufen und die Beträge einzeln abziehen.
Also, wie du schon vermutet hast, dann einzelne Abfragen machen.
Hier würde ich aber vorab noch schauen welche Daten ein Select mit diesem Join liefert.
Aktuell würde ich auf den ersten Blick aber vermuten, dass du alle Fahrzeuge und Garagen des Spielers bekommen solltest.

Hier müsstest du also deine Daten und die Abfrage als Select prüfen.
Wenn dies nicht passt, dann musst du ggf. auf eine Iteration über die Garagen des Spielers gehen und die Beträge dann summieren und vom Spieler abziehen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.807 Beiträge seit 2008
vor 7 Jahren

Stimmt schon, aber wenn man dies über die DB lösen kann, dann sollte man dies auch tun.

Nein, es gibt keine Situation, die dies rechtfertigt.
Datenbanken sind i 99,9% der Fälle der Flaschenhals in der Performance. Zudem sind Datenbank die teuerste Möglichkeit der Skalierung.

Daher sollte man allein deswegen niemals solche Logik in Datenbanken packen.
Davon abgesehen machst Du Dich dann technologisch enorm abhängig. Von Testbarkeit will ich gar nicht anfangen.

Logik gehört in die Logikschickt und nicht in den DAL.

Früher hat man das gerne gemacht; aber man hat aus seinen Fehlren gelernt.

T
2.219 Beiträge seit 2008
vor 7 Jahren

@Abt
Es ging mir dabei nicht darum, die Logik komplett in der DB abzubilden.
Ich bezog mich eher auf die Anweisung oben.
Dort macht es Sinn die DB mit einer Abfrage laufen zu lassen als erst alle Daten einladen und durch zu laufen um dann nochmal einzelne Updates durchzuführen.

Wenn man das Problem mit einer Anweisung in der DB lösen kann, dann sollte man dies auch tun.
Dies hat weniger mit Abbilden der Logik als mehr dem besseren ausnutzen der DB für bessere Performance zu tun.

In diesem Fall, muss er ggf. schon die Daten durchlaufen und dann eine Summe bilden und dann mit einer Update Anweisung den Betrag abziehen.

Die DB ist bei meinen aktuellen und vergangenen Projekten nur selten der Flaschenhals gewesen.
Das größere Problem ist eher, die Datenverarbeitung performant zu lösen.
Bei den Datenmengen die wir hier teilweise in einem Großprojekt verarbeiten, habe wir schon die DB soweit wie möglich optimiert.

Wenn ich ein Projekt umsetze, habe ich mich eigentlich schon auf die Technologie festgelegt.
Ein Wechsel mitten drin würde nur in sehr seltenen Fällen passieren.
Natürlich sollte man denoch die Abhängigkeiten klein halten bzw. wenn möglich sogar keine Abhängigkeiten aufbauen um spätere Migrationen auf andere Systeme durchzuführen.

Warum die Testbarkeit darunter leidet, kann ich nicht ganz nachvollziehen.
Wenn ich die gesamte Logik, entgegen jeden Sinns, in die DB packen würde wäre es klar.
Davon gehst du wohl aus oder?

@lazy
Aktuell wäre der beste Ansatz alle Fahrzeuge aus den Garagen des Spielers einzuladen.
Dann must du nur schauen welche Mieten fällig sind.
Daraus dann die Summe bilden und vom Geld des Spielers abziehen.
Entsprechende Fallstricke wie zu große Beträge musst du dann entsprechend abfangen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

709 Beiträge seit 2008
vor 7 Jahren

Warum die Testbarkeit darunter leidet, kann ich nicht ganz nachvollziehen.
Wenn ich die gesamte Logik, entgegen jeden Sinns, in die DB packen würde wäre es klar.

Ich behaupte mal pauschal, dass jeder noch so kleine Logikteil, den die Datenbank übernimmt, nicht testbar ist.

16.807 Beiträge seit 2008
vor 7 Jahren

Datenbanklogik lässt sich nie 100% als Unit Test abbilden; nur als Integrationstest.
Ebenso braucht man dafür extra Tools wie das TSQL Framework.

Zudem ist es ein Unding, dass zwei zusammenhängende Logikelemente (Datenbank, Anwendung) getrennt getestet werden.
Egal wie lang der Text ist: Logik hat in der Datenbank nichts zu suchen. Und nein, auch dieser Fall macht absolut keinen Sinn diese in der DB laufen zu lassen.
Das ist und bleibt Anwendungslogik und gehört nicht in die DB.

Ja, man legt sich fest auf eine Datenbanktechnologie wie "relationale Datenbank", aber man sollte sich - sofern möglich - nicht auf eine Datenbank wie "wir nehmen nur MySQL" festlegen.
Das ist einfach fahrlässig und sowas würde ich auch floppsig als "dumm" bezeichnen.

Das merkt man nämlich jetzt an Wordpress:
es gibt den massiven Bedarf und Wunsch Wordpress in Cloud-Umgebungen zu nutzen, die aber besonders im Enterprise-Umfeld eben kein MySQL sind.
Wordpress hat sich aber auf MySQL fixiert, verwendet technologisch spezielle MySQL Features; und das ist in meinen Augen ein riesiger, fataler Fehler in Design und Politik.

Und auch hier sehe ich absolut keine Notwendigkeit eine Software auf eine spezifische Datenbank zu programmieren.
Das ist ein Fehldesign und ein fataler Fehler.

Wenn Du, T-Virus, bisher die Datenbank nicht als Flaschenhals hattest, dann hast Du vermutlich(?) noch nicht an einer größeren Anwendung gearbeitet.
Es ist Fakt, dass Datenbanken das Element in Plattformen sind, das am aufwändigsten und weit aus teuersten zu skalieren ist.
Sich das anzugewöhnen ist: schlecht.

T
2.219 Beiträge seit 2008
vor 7 Jahren

@Abt
Soweit kann ich dir folgen und stimme dir auch zu.
Was die Erfahrungen mit Datenbanken angeht, muss ich dir teilweise wiedersprechen.

Aktuell entwickle ich in unserer Firma an unserer Flöttenlösung zur Fahrzeugflotten Überwachung.
Diese händelt aktuell rund 4.000+ Fahrzeuge bei unserem größen Partner die in regelmäßigen Abständen GPS Daten sowie bei LKWs Daten vom canbus senden.
Dort habe wir schon durch entsprechende Optimierungen auf Anwendungsebene sowohl die Speicherung (BulkInsert) als auch die Verarbeitung(Laden/Updaten) der Daten innerhalb der Datenbank nicht als Flaschenhals.

Mehr Aufwand haben wir aber bei der Auswertung der Daten in den Anwendungen.
Wenn ein Kunde mal seine Fahrzeug Daten des letzten Jahres auswerten lässt, dann haben wir eher eine Wartezeit beim auswerten der Daten.
Das einladen/speichern/bearbeiten innerhalb der Datenbank ist hier kein Flaschenhals.
Dafür ist unsere aktuelle Hardware auch ziemlich gut ausgewählt und bietet auch noch Luft nach oben.

Aktuell arbeiten wir mit diesem und anderen aktiven Produkten auf MS SQL.
Wir sind aber auch schon mit PostgreSql am testen einer preiswerten Aternative, die uns massiv Lizenzkosten bei neuen Produkten sparen soll.
Hier ist dann wohl auch die Anschaffung einer eigenen Hardware geplant.
Diese dürfte dann auch gut ausgestattet sein, um sich auf Jahre hin genug Luf nach oben zu halten.
Gerade bei der aktuellen Hardware haben wir schon eine gute Referenz für neue Hardware.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

5.657 Beiträge seit 2006
vor 7 Jahren

Hi T-Virus,

das ist alles sehr interessant (ich lese gerne, wenn Leute aus dem Nähkästchen plaudern) - aber in dem Fall ist das nicht sehr hilfreich. Es geht ja hier nicht um eine Flottenverwaltung oder Log-Funktion, sondern um ein Spiel.

Wenn man ein Spiel entwickelt, dann gibt es wirklich keinen Grund, die Logik in SQL zu implementieren. Wie will man das testen? Wie will man Spielzustände validieren und dem Spieler einen aussagekräftigen Hinweis zukommen lassen? Andere gute Gründe hat Abt ja auch schon genannt. Ich würde jedenfalls empfehlen, die Spielelogik in C# zu implementieren, und die Datenbank nur zum Speichern und Laden des aktuellen Spielstands verwenden.

Weeks of programming can save you hours of planning

D
985 Beiträge seit 2014
vor 7 Jahren

Ich sehe aber bei einer Flottenverwaltung erst Recht keinen Grund die Logik (ganz oder teilweise) in SQL zu implementieren.

T
2.219 Beiträge seit 2008
vor 7 Jahren

@MrSparkle + Sir Rufo
Mein Text ist hier leider nicht ganz klar.
Es geht nicht darum die Logik soweit wie möglich in die DB zu verlagern, wäre auch eine Katastrophe.
Hier ging es nur um die Last auf DB Ebene, wie Abt mit den 99.9% Falschenhals angedeutet hatte.
Die Logik bei unserer Lösung ist auch im Drei Schichten Modell abgebildet.

Ich habe noch ein paar alte Projekte, die noch ohne dieses Modell umgesetzt wurden.
Dort wurde munter frühlich die UI samt DB Anweisungen gemischt.
Wie das ganze endet, kann sich jeder denken.
Es ist im Einsatz aber wirklich Warten will das keiner.
Aber das ist eine andere Baustelle.

Ansonsten hatte ich oben auch schon mit dem Drei Schichten Modell sowie dem einladen und summieren der Werte mit der "einen" Update Anweisung schon einen Ansatz samt Logik im Code gegeben.
Das dürfte als Ansatz passen, ob es umgesetzt werden kann/wird muss der OP sagen/prüfen.

Natürlich würde ich das Thema noch weiter verfolgen, da mich das schon interessiert.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

H
523 Beiträge seit 2008
vor 7 Jahren

Interessantes Thema 😃
Wie sieht es denn dann mit Stored Procedures aus? Setzt Ihr die ein?

Bei uns sind einige Funktionen (z. B. Teile einer sehr umfangreichen Preisfindung) über Stored Procedures realisiert, weil dadurch erhebliche Performanceverbesserungen erzielt werden konnten.

16.807 Beiträge seit 2008
vor 7 Jahren

Nie. Gleicher Grund wie Logik in der Datenbank.

Dass sie (heute noch) pauschal eine bessere Performance haben, ist ein irrglaube und wurde mittlerweile in genug Tutorials, Blogs, Vorträgen und Co widerlegt.
Früher war das mal wirklich so, aber ist einige einige Jahre her.

Stored Procedures Are Faster Than SQL Code
This is a myth, the performance is always equivalent, from the book:
>

Wenn eine SP performanter als ein Query ist, dann ist der Query sch*.

D
985 Beiträge seit 2014
vor 7 Jahren

Sagen wir mal so, die Datenbank liegt auf einem Hyper-Prn-Rechner (RAM, HDD, CPU alles groß und sauschnell) und der Anwendungsrechner ist eine Schnarchkröte aus dem letzten Jahrhundert mit einem Kern, ganz wenig RAM und im Hintergrund wird noch die Formel zur Erringung der Weltherrschaft errechnet und die Anbindung an den Server erfolgt über ein 16K-Modem dann wird eine SP immer schneller zum Ergebnis kommen als der Rechner (wenn die Daten erst zum Rechner müssen, dort verarbeitet werden um das Ergebnis zu ermitteln).

In dieser Beschreibung ist allerdings fast jeder Detailpunkt ein genereller Fehler in der Umgebung 😁