SELFPHP: Version 5.8.1 Befehlsreferenz - Tutorial – Kochbuch – Forum für PHP Einsteiger und professionelle Entwickler

SELFPHP


Professional CronJob-Service

Suche



CronJob-Service    
bei SELFPHP mit ...



 + minütlichen Aufrufen
 + eigenem Crontab Eintrag
 + unbegrenzten CronJobs
 + Statistiken
 + Beispielaufrufen
 + Control-Bereich

Führen Sie mit den CronJobs von SELFPHP zeitgesteuert Programme auf Ihrem Server aus. Weitere Infos



:: Buchempfehlung ::

PHP 5.3 & MySQL 5.1

PHP 5.3 & MySQL 5.1 zur Buchempfehlung
 

:: Anbieterverzeichnis ::

Globale Branchen

Informieren Sie sich über ausgewählte Unternehmen im Anbieterverzeichnis von SELFPHP  

 

:: Newsletter ::

Abonnieren Sie hier den kostenlosen SELFPHP Newsletter!

Vorname: 
Name:
E-Mail:
 
 

Deine Leidenschaft ist die Unterwasserfoto-grafie?


Dann ist Qozido genau das Richtige für Dich!

Die Bilderverwaltung mit Logbuch für Taucher und Schnorchler ist da!

www.qozido.de

 


Zurück   PHP Forum > SELFPHP > MySQL

MySQL Anfänger, Fortgeschrittene oder Experten können hier Fragen und Probleme rund um MySQL diskutieren

Antwort
 
Themen-Optionen Ansicht
  #1  
Alt 19.04.2012, 14:00:06
Methos Methos ist offline
Anfänger
 
Registriert seit: Apr 2012
Alter: 38
Beiträge: 3
Methos befindet sich auf einem aufstrebenden Ast
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
  #2  
Alt 19.04.2012, 15:05:26
Methos Methos ist offline
Anfänger
 
Registriert seit: Apr 2012
Alter: 38
Beiträge: 3
Methos befindet sich auf einem aufstrebenden Ast
AW: Performance Problem mit konkurierenden SELECT und UPDATE Anweisungen

Ergänzung:

Also zum 2. Teil, dem übertragen der Daten aus der tostats_daycounter in die eigentliche Tabelle nachts, habe ich inzwischen meinen - zugegebener Maßen saudämlichen - Fehler gefunden:

Die WHERE Bedingung hat gefehlt, also hat das Skript aus der daycounter eine Wert ausgelesen und auf alle knapp 60.000 Einträger der Counter Tabelle aufaddierte, und das in 3 Spalten und mit LOW_PRIORITY .. dass das nicht besonders schnell geht kann ich mir sogar vorstellen.

Das Skript MIT WHERE Bedingung ist dann für 3000 Einträge in nichtmal 3 Minuten durchgelaufen. Das fällt in die Kategorie: wie erwartet.

Das Ursprungsproblem bleibt damit aber noch ungelöst.
Dort kommt bei einem Eintrag in die topstats_counter Tabelle kein LOW_PRIORITY in Frage, da damit der Seitenaufbau aufgehalten wird, wenn das Update warten muss. (Soweit ich weiss wartet PHP bis es eine Antwort bekommt, falls das falsch ist, oder es einen Weg gibt, das für einzelne Query abzustellen wäre das ne Lösung)
Mit Zitat antworten
  #3  
Alt 20.04.2012, 00:35:25
Ckaos Ckaos ist offline
Member
 
Registriert seit: Nov 2007
Beiträge: 799
Ckaos befindet sich auf einem aufstrebenden Ast
AW: Performance Problem mit konkurierenden SELECT und UPDATE Anweisungen

Hi

Zitat:
auch wenn ich nun schon seit Jahren mit MySQL arbeite
Hast du dir das Konstrukt ausgedacht?
Ich fass mal zusammen:
Zitat:
Tabelle topstats_counter mit den 4 Feldern nid, count, weekcount, monthcount
...
geupdatet sobald ein mit nid verknüpfter Inhalt aufgerufen wird
...
ca 60.000 möglichen nids
Hmm also du hast für jeden möglichen Inhalt nen Countereintrag den du
einzeln aktualisierst?
Setz du jeden Monatsersten dann "monthcount" auf null?
Was spricht gegen eine Tabelle mit id,nid,datum und einigen
Rechenbefehlen?
ala
Code:
SELECT nid,COUNT(*) AS Hits FROM HITTAB WHERE datum=current_date() GROUP BY nid ORDER BY Hits DESC
mfg

CKaos
__________________
"Wenn die Leute Häuser so bauen würden, wie wir Programme schreiben, würde der erstbeste Specht unsere Zivilisation zerhacken."
In den allermeisten Fällen sitzt der Bug etwa 40 cm vor dem Monitor!
Mit Zitat antworten
  #4  
Alt 12.12.2012, 12:33:43
Methos Methos ist offline
Anfänger
 
Registriert seit: Apr 2012
Alter: 38
Beiträge: 3
Methos befindet sich auf einem aufstrebenden Ast
AW: Performance Problem mit konkurierenden SELECT und UPDATE Anweisungen

So nach dem ich zum einen mit anderen Aufgaben beschäftigt war und zu dem wohl nciht mitbekommen habe, das ich hier eine Antwort bekommen hatte, bin ich wieder bei meinem Performanceproblem angekommen.

Somit auf zur nächsten Runde.

Also, warum das von mir gewählte Konstrukt und nicht eine Tabelle die einfach nur jeden Hit speichert..

Naja ich habe auf der Webseite zahlreiche Anzeigen für die User in denen Inhalte innerhalb ihrer Kategorie nach ihrer Beliebtheit sortiert angezeigt werden.

Ich kann mir eigentlich nciht vorstellen, das es performanter sein soll, für alle Inhalte zu ermitteln wie oft sie ( in einem Zeitraum ) aufgerufen wurden, und dass dann nach Inhalttyp und Kategorie wegzufiltern.

Der Hintergrund ist folgender:

Inhalte können von verschiedenen Typen sein und in verschiedenen Kategorien.

Nehmen wir mal an wir haben TypA und KatB.

Nach deinen Vorschlag müßte ich jetzt erstmal für ALLE Inhalte die Berechnung ausführen, danach sortieren, alle Elemente des TypA raussuchen und danach noch prüfen ob die Elemente in KatB sind. Die 5 beliebtesten geb ich dann aus ...

Da ich davon ausgehe das ich wesentlich mehr SELECTs als UPDATEs habe bin ich einfahc mal davon ausgegangen, das es sinnvoller ist, die Werte bei jedem Update zu aktualisieren, als alle Werte jedesmal zusammenzurechnen.

Der counter Wert ( der halt ALLE jemals erfolgten Aufrufe enthält ) wird z.B. bei JEDEM anzeigen des Inhaltes auf der Webseite ausgegeben und soll sich auch jedesmal ändern wenn ein Aufruf erfolgt ist. Da einmal am Tag ne Tabelle zu erzeugen die quasi einen snapshot des aktuellen Stands darstellt, ist somit auch keine Lösung.
Und bei den Hits die so über die Seite laufen jedes mal alle Einträge zu zählen die zu einer nid gehören macht mir performance technisch schon etwas sorgen.

Was ich aber letztlich zur Zeit nicht verstehe ist, warum ein update auf die Tabelle zur Zeit zwischen 200ms und 700ms dauert. Er soll doch nur die 3 Werte um eins erhöhen und schreiben, und die entsprechenden Indizes aktualisierten.

Wenns keine innodb tabelle wäre würd ich ja annehmen, das er die Tabelle nicht gelockt bekommt, aber da er bei inno nur eine Zeile sperren muss, wundert mich das doch reichlich.

Hat vll noch jemand eine Idee, einen Vorschlag, oder evtl. einen Link mit Infos die zu diesem Problem passen?
Mit Zitat antworten
  #5  
Alt 12.12.2012, 12:55:01
DokuLeseHemmung DokuLeseHemmung ist offline
SELFPHP Experte
 
Registriert seit: Jun 2008
Beiträge: 2.241
DokuLeseHemmung befindet sich auf einem aufstrebenden Ast
AW: Performance Problem mit konkurierenden SELECT und UPDATE Anweisungen

Zitat:
und die entsprechenden Indizes aktualisierten.
Da scheint mir der Hase im Pfeffer zu liegen.

SELECTs warten nicht auf UPDATEs, ohne explizite LOCKs, es sei denn, es teilen sich alle Scripte die selbe persistente Verbindung.
Mit Transactions lässt was einrichten, bzw. Race Conditions abfangen.
Aber dadurch wirds auch nicht schneller.

Evtl. zeigt dir ja "EXPLAIN SELECT ....." etwas.
Mit Zitat antworten
Antwort

Stichworte
innodb, lock, myisam, mysql, performance


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind aus.
[IMG] Code ist aus.
HTML-Code ist aus.

Gehe zu

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
To Many Connections ProGamer11 PHP Grundlagen 0 19.06.2003 00:52:56
Problem mit UPDATE Darksaber PHP für Fortgeschrittene und Experten 1 03.05.2003 14:16:37
update formular problem Silencer PHP für Fortgeschrittene und Experten 1 14.10.2002 09:29:44
SQL Select Problem HS-78 PHP für Fortgeschrittene und Experten 5 14.08.2002 10:02:44
problem mit update Paul PHP für Fortgeschrittene und Experten 4 22.06.2002 01:04:20


Alle Zeitangaben in WEZ +2. Es ist jetzt 04:33:08 Uhr.


Powered by vBulletin® Version 3.8.3 (Deutsch)
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.


© 2001-2014 E-Mail SELFPHP OHG, info@selfphp.deImpressumKontakt