MySQL (Update)

Wichtiger Hinweis: Bitte ändert nicht manuell die Schriftfarbe auf schwarz sondern belasst es bei der Standardeinstellung. Somit tragt ihr dazu bei dass euer Text auch bei Verwendung unseren dunklen Forenstils noch lesbar ist!

Tipp: Ihr wollt längere Codeausschnitte oder Logfiles bereitstellen? Benutzt unseren eigenen PasteBin-Dienst Link
  • Liebe Community,


    mein Server hat derzeit das MySQL-System, dieses hat 109 Felder pro Spieler.
    Wenn alle Accounts gespeichert werden, beginnt der Server für einige Sekunden sich aufzuhängen.


    Das könnte man mit OnQueryFinish etwas beheben, jedoch finde ich diese Möglichkeit recht kompliziert.


    Zur Frage:
    Ist es möglich, einen Update-Befehl zu schreiben, der die ganze Reihe aktualisiert,
    ohne jeden Wert abzufragen?


    Code
    ID  PERSONALNUMMER  NAME      VORNAME  GEBURTSDATUM  TELEFON         (und noch mehr)13      60001       Aagenau   Karolin  02.01.1950    0234/66006001    usw.18      80002       Aliman    Zafer    12.11.1965    0201/4012161     usw.

    Beispiel
    UPDATE * FROM Accounts (13,60002,'Bayern','Max','05.01.1950','2398/238902389') WHERE ID = 13

  • SQL
    UPDATE `Accounts` SET `PERSONALNUMMER` = '6002', `NAME` = 'Bayern', `VORNAME` = 'Max' [usw...] WHERE `ID` = '13'


    Ich fürchte du hast meine Frage nicht verstanden.


    Dieser MySQL-Query benötigt ziemlich lange, weil er jeden Wert mit dem Feldnamen überprüft werden muss.
    Sind von dieser Abfrage mehrere, mit circa 110 Werten, führt es bei einem gut gefüllten Server zu mehreren Sekunden laggs.
    ich fragte ob es noch Alternativen gibt.


    Server Laggs
    [20:14:00]

    Code
    Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:00] Account ... wurde gespeichert. Dies dauerte 0 Millisekunden.[20:14:00] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:01] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:01] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:01] Account ... wurde gespeichert. Dies dauerte 0 Millisekunden.[20:14:02] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:02] Account ... wurde gespeichert. Dies dauerte 0 Millisekunden.[20:14:02] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:02] Account ... wurde gespeichert. Dies dauerte 0 Millisekunden.[20:14:03] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:03] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:03] Account ... wurde gespeichert. Dies dauerte 0 Millisekunden.[20:14:04] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:04] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:04] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:05] Account ... wurde gespeichert. Dies dauerte 0 Millisekunden.[20:14:05] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:05] Account ... wurde gespeichert. Dies dauerte 0 Millisekunden.[20:14:05] Account ... wurde gespeichert. Dies dauerte 0 Millisekunden.[20:14:06] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:06] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:06] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:06] Account ... wurde gespeichert. Dies dauerte 0 Millisekunden.[20:14:07] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:07] Account ... wurde gespeichert. Dies dauerte 0 Millisekunden.[20:14:07] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.[20:14:08] Account ... wurde gespeichert. Dies dauerte 20 Millisekunden.

    Server Laggs
    Namen wurden rauseditiert.
    Was seltsam ist, dass die Accoutspeicherung entweder 0 oder 20 Millisekunden dauert.
    Und trotz dieser geringen Dauer (28 Accounts gespeichert, 28*20 = 560ms = 0,56 sekunden)
    laggt der Server ganze 8 Sekunden.

    2 Mal editiert, zuletzt von Pille ()

  • Einfachste art ist es nicht alle gleichzeitig zu updaten.


    Ansonsten würde ich es so probieren:

    SQL
    UPDATE `Accounts` SET `PERSONALNUMMER` = '6002', `NAME` = 'Bayern', `VORNAME` = 'Max' [usw...] WHERE `ID` = '13';UPDATE `Accounts` SET `PERSONALNUMMER` = '6002', `NAME` = 'Bayern', `VORNAME` = 'Max' [usw...] WHERE `ID` = '14';UPDATE `Accounts` SET `PERSONALNUMMER` = '6002', `NAME` = 'Bayern', `VORNAME` = 'Max' [usw...] WHERE `ID` = '15';


    habe es jedoch noch nie ausprobiert.

  • Dann muss ja der string... 512*7 = ca. 3500 Arrays haben.
    Macht das was? Oder kann ich das irgendwie anders lösen?


    Das nennt man Zellen, nicht Arrays. Pawno stellt sich hier sehr komisch an - das wirst du nicht anderst hinbekommen.



    Einfachste art ist es nicht alle gleichzeitig zu updaten.


    Ansonsten würde ich es so probieren:
    [...]
    habe es jedoch noch nie ausprobiert.


    Das wird so nicht funktionieren. Man kann jedoch das Multi-Insert Verfahren anwenden, wenn man einen Primary Key gesetzt hat (hier zB. ID):


    SQL
    INSERT INTO `Accounts` (`ID`, `PERSONALNUMMER`, `NAME`)
    VALUES (13, 60001, 'Aagenau'),
           (16, 80002, 'Aliman')
    ON DUPLICATE KEY UPDATE `PERSONALNUMMER` = VALUES (`PERSONALNUMMER`), `NAME` = VALUES (`NAME`);
  • mach es per strcat
    damit kannst du die 7 formats zusammenpacken und dann per 1 Query speichern lassen


    nichtmal strcat brauchst du :D es reicht auch ein großer string mit \ kann man einen zeilebruch bezwecken.


    @ Pille eine andere möglichkeit die accounts zu updaten hast du leider nicht ^^ als in ihrgend einer Form mit UPDATE zu arbeiten


    als kleiner tipp benutzt doch mysql_format und den platzhalter %e dann werden die strings automatisch escaped.
    Aber nun gut es ist auch teilweise auch besser mehrere kleine querys abzusenden als ein sehr großes
    zu dem wenn du willst kannst du auch einen anderen syntax dazu verwenden
    UPDATE `Accounts` SET (PERSONALNUMMER, NAME, ...) = (6002, 'Max', ...)

  • Das wird so nicht funktionieren. Man kann jedoch das Multi-Insert Verfahren anwenden, wenn man einen Primary Key gesetzt hat (hier zB. ID):


    Das klingt nach der Lösung des Problems, funktioniert aber leider bei mir nicht.


    Habe mir folgende Tabelle erstellt:


    Nun habe ich 2 Testreihen erstellt:


    Und hier der Query den ich eingebe:

    SQL
    INSERT INTO TestTabelle (ID,Name,Test,Test2,Test3) VALUES (1,'ABC',88,12,999) ON DUPLICATE KEY UPDATE Name = VALUES (Name), Test = (Test), Test2=(Test2),Test3=(Test3);


    MySQL meldet:

    Code
    /* 0 rows affected, 0 rows found. Duration for 1 query: 0.000 sec. */


    Und die Tabelleninhalte werden nicht geupdated...
    Ist was am Code falsch?

  • do.de - Domain-Offensive - Domains für alle und zu super Preisen
  • Ich bezweifle, dass man mit dem Optimieren von Queries die Geschwindigkeit auf unter 1 Sek. verbessern kann. OnQueryFinish wurde genau für solche Fälle gemacht, um große Querys in einem separaten Thread abzuschicken. Setz dich damit auseinander, es ist wirklich nicht schwer. Und wenn du was nicht verstehst, dann kannst du ja hier nachfragen.

  • schwer ist es nicht, nein, aber das Problem ist folgendes:


    Bei einer Endround sollen zuerst alle Accounts gespeichert werden.
    Erst dann soll die Endround erfolgen (Rcon: "gmx").
    Dadurch, dass mehrere Threads eröffnet werden, kann nicht geprüft werden,
    wann denn alle Accounts gespeichert werden.

  • Du kannst dir auch mal "Transactions" ansehen:
    http://dev.mysql.com/doc/refman/5.5/en/commit.html

    Zitat

    By default, MySQL runs with autocommit mode enabled. This means that as soon as you execute a statement that updates (modifies) a table, MySQL stores the update on disk to make it permanent. The change cannot be rolled back.


    Das brauchst du ja nicht unbedingt.



    Zitat

    Bei einer Endround sollen zuerst alle Accounts gespeichert werden.
    Erst dann soll die Endround erfolgen (Rcon: "gmx").
    Dadurch, dass mehrere Threads eröffnet werden, kann nicht geprüft werden,
    wann denn alle Accounts gespeichert werden.


    Für den Fall die Querys werden in der Reihenfolge abgehandelt, in der sie an die Datenbank gesendet wurden, kannst du auch einfach eine Dummy Anfrage machen.
    Zum Beispiel:

    SQL
    SELECT NOW()


    Wenn diese durchgeführt wurde ( extra Thread natürlich ) , dann machst du den gmx per rcon. Sollte doch dein letztes Problem lösen.

  • Du kannst dir auch mal "Transactions" ansehen:
    http://dev.mysql.com/doc/refman/5.5/en/commit.html


    Ohje, das müsstest du mir jetzt aber schon genauer erklären, mit der SAMP-Wiki komme ich ganz gut zurecht,
    aber diese MySQL-Wikis sind so komplex, sogar im deutschen, dass ich jedesmal beim lesen kläglich scheitere ^^


    Wenn diese durchgeführt wurde ( extra Thread natürlich ) , dann machst du den gmx per rcon. Sollte doch dein letztes Problem lösen.


    Bei Select Now() gibt er die aktuelle Uhrzeit (& Datum) aus.
    Wie soll ich das überprüfen?


    //Edit: Du menist ich sende die Now() Anfrage, nach allen Accountspeicherungen,
    und sobald diese ausgeführt ist, startet der Server?


    Wo wir schonmal dabei sind: Was ist schneller? Gettime bzw. gettdate oder das ganze
    über MySQL: Now(), UNIX_TIMESTAMP() etc.

  • Dann versuch es mal mit dem Deutschen Dokumentation:
    http://dev.mysql.com/doc/refman/5.1/de/commit.html


    Zitat

    //Edit: Du menist ich sende die Now() Anfrage, nach allen Accountspeicherungen,
    und sobald diese ausgeführt ist, startet der Server?


    So ähnlich.Du kannst von mir aus auch "SELECT 1" machen, macht keinen Unterschied.
    Wenn du weisst dass diese Dummy Anfrage durchgeführt wurde ( SELECT NOW() ) ,dann sind auch alle Anfragen die davor waren durchgeführt worden ( Accountspeicherung ) .
    Es geht nicht um das Ergebnis der Abfrage. Es geht lediglich darum,ob die Abfrage durchgeführt wurde.


    Was du dann mit der Erkenntnis machst,dass alle Querys durchgeführt wurden, ist dann dir überlassen.


    Zitat

    Wo wir schonmal dabei sind: Was ist schneller? Gettime bzw. gettdate oder das ganze
    über MySQL: Now(), UNIX_TIMESTAMP() etc.


    Da kann ich dir keine gute Antwort drauf geben.


    //Edit:
    Wichtig:
    Das klappt aber auch nur,wenn alle Querys in der Reihenfolge abgearbeitet werden in der sie an den Server gesendet wurden.

    Einmal editiert, zuletzt von Goldkiller ()

  • Du stellst dich dann aber ganz schön faul an. Man findet tonnenweise Erklärungen,wie das funktioniert. Ich selber bin kein Experte auf dem Gebiet, will dir daher auch keine falschen Informationen geben. Dennoch findest du hier eine Erklärung der Funktionen:

    Zitat

    These statements provide control over use of transactions:
    START TRANSACTION or BEGIN start a new transaction.
    COMMIT commits the current transaction, making its changes permanent.
    ROLLBACK rolls back the current transaction, canceling its changes.
    SET autocommit disables or enables the default autocommit mode for the current session.


    Warum man es machen sollte,steht hier:

    Zitat

    By default, MySQL runs with autocommit mode enabled. This means that as soon as you execute a statement that updates (modifies) a table, MySQL stores the update on disk to make it permanent. The change cannot be rolled back.
    bzw:
    Standardmäßig läuft MySQL im Autocommit-Modus. Das bedeutet, dass, sobald eine Anweisung ausgeführt wird, die eine Tabelle aktualisiert (also ändert), MySQL diese Änderung auf Festplatte speichert.


    Ich wüsste wirklich nicht,wieso ich dir die Erklärungen nochmal schreiben sollte obwohl es sie schon super gibt :S .
    Du brauchst das auch nicht unbedingt.Wenn es dir zu kompliziert ist,dann lass es lieber.
    Der Trick mit dem Dummy Query müsstest du mit oder ohne Transaction sowieso nutzen.