Einzelnen Beitrag anzeigen
  #1  
Alt 19.04.2012, 13:00:06
Methos Methos ist offline
Anfänger
 
Registriert seit: Apr 2012
Alter: 47
Beiträge: 3
Performance Problem mit konkurierenden SELECT und UPDATE Anweisungen

Hallo,

auch wenn ich nun schon seit Jahren mit MySQL arbeite bin ich nun mit meinem Latein bei meinem aktuellen Problem am Ende.

Folgendes Szenario:

Ich habe eine Tabelle topstats_counter mit den 4 Feldern nid, count, weekcount, monthcount alle vom Typ int. Auf allen Feldern liegt ein Index, da über die count Felder sortiert wird, nid ist der Primärschlüssel. Das Tabellenformat ist Innodb.

Innodb wurde gewählt, da - soweit mein Kenntnisstand - Innodb bei einem Update nur die betroffene Zeile sperrt, MyISAM aber mal gepflegt die gesamte Tabelle.

Die Tabelle wird mit dem Statement
Code:
UPDATE topstats_counter SET count = count +1, weekcount=weekcount+1, monthcount=monthcount+1 WHERE nid = 123
geupdatet sobald ein mit nid verknüpfter Inhalt aufgerufen wird. (nid ist die ID eines Nodes in Drupal). Zu gut deutsch ein simpler Hitcounter.

An sich aus meiner Sicht mal so gar nix besonderes. Allerdings scheinen die Updates normale Selects brutal auszubremsen, so daß die Webseite quasi zum Stillstand kommt, da keine Daten mehr abgerufen werden können.

Auf Grund dieser Situation bin ich auf die Idee gekommen, in einer seperaten Tabelle nur für einen Tag die Hits zu speichern. Die Tabelle heißt topstats_daycounter und hat die Felder nid und count, wobei nid wieder Primärschlüssel ist.

Das läuft erstmal soweit gut, da nur Updates auf dieser Tabelle stattfinden, aber eben keine Selects.

Wenn ich nun aber versuche mittels eines PHP-Skripts nachts die Tageswerte in die topstats_counter Tabelle zu übertragen, wird das Skript nicht wirklich fertig.

Folgendes mache ich dazu:

- Alle Werte aus topstats_daycounter holen ( nid, count paare)
- mit einer Schleife über diese Elemente drüberlaufen und mit einem

Code:
UPDATE LOW_PRIORITY topstats_counter SET count = count +x, weekcount=weekcount+x, monthcount=monthcount+x WHERE nid = 123
zu aktualisieren. (Wobei das x natürlich nun nur ein Platzhalter für den Wert von count aus der topstats_daycounter ist und 123 nur ein Platzhalter für die jeweilige nid.

Ich dachte mir, ich setze (vermeintlich) wohlweisslich mal 'LOW_PRIORITY' ein, damit mir nicht noch eventuelle Selects in die Quere kommen.

Das Skript wurde nachts um 4:00h gestartet und lief um 10:30h immer noch ( bei ca 3000 Einträgen in der topstats_daycounter).

Ich hab also mit
Code:
SHOW PROCESSLIST;
geguckt ob ich sehen kann wodrauf die Updates denn bitte warten .... da ist nur die meiste Zeit nix wodrauf die warten könnten. Die Processliste weist die meiste Zeit 2 Befehle aus, mein Update und mein Show. Selects sind nur ab und an mal kurz zu sehen.

Zumal ich es bei ca 60.000 möglichen nids ( sprich vorhandenen Einträgen) recht unwahrscheinlich finde, dass immer genau der Eintrag gerade per SELECT abgerufen werden soll, der auch gerade geupdated wird.

Die ganze - für mich -etwas seltsame Situation wirft einige Fragen auf:

1.) Ist das ganze Theater ein Problem von InnoDB und wenn ja warum? Eigentlich sollte doch auf Grund des Rowlocks genau so etwas nicht auftreten, oder 'spinnt' MySQL bei der Verbindung von MyISAM und InnoDB tabellen rum?

2.) Wie kann man das ganze so bauen das es performant läuft. ( Bevorzugt wird eine direkte Aktualisierung der Daten wie in der ersten Anweisung, der Umweg über die daycounter-Tabelle ist eher als Notlösung zu sehen )

3.) Bringt in diesem Context eine Stored Procedure etwas? Die Anweisung ist ja an sich immer die Selbe, lediglich mit einem veränderlichen Parameter, nämlich die nid.

4.) Wo habe ich evtl in meiner Logik einen kapitalen Denkfehler?

5.) Kann man per SQL eine Zeile Locken ( auf Innodb-Tabelle versteht sich), den Wert auslesen, ihn erhöhen, zurückschreiben und die Zeile wieder unlocken? Ist das ggf performanter als meine +1 Anweisung, obwohl ich ne ganze Transaktion da draus mache?

Fragen über Fragen. Ich würde mich über Hinweise zu dem geschilderten Problemen sehr freuen.
Mit Zitat antworten