Falls noch jemand das gute alte Semmelstatz für seine Blog Statistiken benutzt und findet, dass die Anzeige der Statistiken im Admin Bereich zu lange dauert sollte er ein wenig Hand anlegen. Mit nur wenigen Schritten ist Semmelstatz pfeilschnell.
Da ich selbst ein Gewohnheitstier bin und nur ungern auf neue Systeme umsteige wenn sich die alten bewährt haben ist bei mir immer noch Semmelstatz im Einsatz um Blog Statistiken erfassen zu können. Den Aufzeichnungen von Semmelstazt verdankt ihr die Suchbegriffe des Monats. ![]()
Problem ist allerdings, dass die Anzeige der Statistiken im Admin bereich von Wordpress super langsam ist wen man erst einmal ein paar Einträge in der Datenbank hat. Da kann das schon mal 2 Minuten dauern. Viel zu lange!
Der Grund dafür sind sehr schlechte Datenbank Queries. Die Indizes werden z.B. nicht genutzt was bedeutet, dass MySQL jedes mal die gesammte Datenbank durchsuchen muss.
Durch ein paar Modifikationen der Abfragen lässt sich das ganze aber beschleunigen. Was vroher mehrere Minuten dauert geht dann in Sekunden.
Das ganze funktioniert bei Semmelstazt 3.1 und für 3.0.1, da sind die Namen der Aufrufe etwas anders. (statt $wbdb->XXX ist es $this->wpdb->xxx)
Sofern die Datenbankqueries bei äteren Semmelstazt Versionen die selben sind funtioniert es dort natürlich auch.
Die Änderungen werden in der Datei semmelstazt_func.php umgesetzt.
Die drei großen Flaschenhälse sind:
- Die Statistik Anzeige für heute
- Die Statistik Anzeige der letzten X Tage
- Die Top 10 Beiträge
Lösung:
Statistik Anzeige für heute
In der Semmelstatz Tabelle einen Index auf das Feld “time” setzen.
In der Funktion sem_showTodayStatz() die Query
SELECT COUNT(ip) AS hits, COUNT(DISTINCT ip) AS visitors, COUNT(DISTINCT referer)
AS referers, substring(time,1,10) AS date FROM ".$wpdb->statz." WHERE substring(time,1,10) = CURDATE() GROUP BY date
durch folgende Query ersetzen:
SELECT COUNT(ip) AS hits, COUNT(DISTINCT ip) AS visitors, COUNT(DISTINCT referer)
AS referers, substring(time,1,10) AS date FROM ".$wpdb->statz." WHERE time >= CURDATE() GROUP BY date
Erklärung: Da time das bedingungsfeld ist bracht es einen Index damit die Daten schneller berglichen werden können. Das umschreiben im Query entfern die Berechnung im Bedingungsteil (andernfalls nützt uns der Index nämlich nichts)
Statistik Anzeige der letzten x Tage
Benötigt ebenfalls einen Index auf time. den haben wir ja oben schon gesetzt. Bleibt die Optimierung des MySQL Queries in der Funktion sem_showDailyStatz()
Folgende Query ist gegeben:
SELECT COUNT(ip) AS hits, COUNT(DISTINCT ip) AS visitors, COUNT(DISTINCT referer)
AS referers, substring(time,1,10) AS date FROM ".$wpdb->statz." GROUP BY date ORDER BY time DESC LIMIT 0, ".$limit
Vor dem Query Aufruf muss noch folgende Zeile hinzugefügt werden:
$daylimit=$limit-1;
Und anschliessend ersetzen wir die Query durch diese, die 8-10 mal schneller ist.
SELECT COUNT(ip) AS hits, COUNT(DISTINCT ip) AS visitors, COUNT(DISTINCT referer)
AS referers, substring(time,1,10) AS date FROM ".$wpdb->statz." WHERE time>=CURDATE()-INTERVAL ".$daylimit." DAY GROUP BY date ORDER BY time DESC");
Erklärung: Die Original Query läd zuerst die Statsitiken aller Tage in der Tabelle und zeigt dann die ersten X davon an. Da uns die anderen gar nicht interessieren können wir der Datenbank die Mühe auch sparen und die zu verarbeitenden Zeilen auch gleich begrenzen und das tun wir mit der Ergänzung des heutigen Datums -des Limits.
Die Top 10 Beiträge
Index auf page in der Statz Tabelle setzen.
In der Funktion sem_showTopReads() die Query
SELECT post_title AS posttitle, post_name as postname, guid AS postid,
COUNT(".$wpdb->statz.".page) AS count FROM ".$wpdb->posts.", ".$wpdb->statz." WHERE
".$wpdb->statz.".page = ".$wpdb->posts.".ID GROUP BY postid ORDER BY count DESC LIMIT 10
durch diese ersetzen, die aus einer 70 Sekunden langen Abfrage eine 2 Sekunden Abfrage macht
SELECT STRAIGHT_JOIN post_title AS posttitle, post_name as postname, guid AS postid,
COUNT(".$wpdb->statz.".page) AS count FROM ".$wpdb->statz.", ".$wpdb->posts." WHERE
".$wpdb->statz.".page = ".$wpdb->posts.".ID GROUP BY page ORDER BY count DESC LIMIT 10");
Erklärung: Straight Join und die Reihenfolge der Tabellen in der Abfrage sind der Schlüsselpunkt. Zudem wird nun nach einem indexierten Feld gruppiert.
Vermutlich lassen sich die anderen Queries ebenfalls optimieren. Diese 3 waren aber die lahmsten. Die anderen nehme ich mir vieleicht auch mal vor wenn sich dadurch noch starke verbesserungen erzielen lassen.









October 20th, 2008 at 08:34
Du hast bei der Funktion “sem_showTodayStatz()” ein “$” vergessen.
Die Abfrage muss lauten:
SELECT COUNT(ip) AS hits, COUNT(DISTINCT ip) AS visitors, COUNT(DISTINCT referer) AS referers, substring(time,1,10) AS date FROM “.$wpdb->statz.” WHERE time >= CURDATE() GROUP BY date
Sonst funktionierts nicht!
October 20th, 2008 at 10:38
gefixt. Danke.