2009-05-20 2 views
1

Jeder Besuch meiner Website aktualisiert den individuellen Trefferzähler eines Benutzers und aktualisiert eine Spalte für time() basierend auf ihrer IP-Adresse und ID, die in einem Cookie gespeichert sind. Also, wenn die Daten zur Ausgabe kommen, was eine effizientere Art und Weise meiner folgenden Code mit weniger Datenbankaufrufe, wie es im Wesentlichen eine Kopie von sich selbst:Finden Sie heraus, wie viele Benutzer in PHP online sind?

<? 
$last1Min = time()-60; 
$last5Mins = time()-300; 
$last1Hr = time()-6000; 
$last1Dy = time()-144000; 
$last1Wk = time()-1008000; 
$last1Mnth = time()-30240000; 

//last1Min 
$sql = "SELECT COUNT(*) FROM usersonline WHERE lastOnline > $last1Min"; 
while($rows = mysql_fetch_array(mysql_query($sql))) { 
    echo "Users online in the last minute: " . $rows['COUNT(*)'] . "<br />\n"; 
} 

//last5Mins 
$sql = "SELECT COUNT(*) FROM usersonline WHERE lastOnline > $last5Mins"; 
while($rows = mysql_fetch_array(mysql_query($sql))) { 
    echo "Users online in the last 5 minutes: " . $rows['COUNT(*)'] . "<br />\n"; 
} 

//last1Hr 
$sql = "SELECT COUNT(*) FROM usersonline WHERE lastOnline > $last1Hr"; 
while($rows = mysql_fetch_array(mysql_query($sql))) { 
    echo "Users online in the last hour: " . $rows['COUNT(*)'] . "<br />\n"; 
} 

//last1Dy 
$sql = "SELECT COUNT(*) FROM usersonline WHERE lastOnline > $last1Dy"; 
while($rows = mysql_fetch_array(mysql_query($sql))) { 
    echo "Users online in the last day: " . $rows['COUNT(*)'] . "<br />\n"; 
} 

//last1Wk 
$sql = "SELECT COUNT(*) FROM usersonline WHERE lastOnline > $last1Wk"; 
while($rows = mysql_fetch_array(mysql_query($sql))) { 
    echo "Users online in the last week: " . $rows['COUNT(*)'] . "<br />\n"; 
} 

//last1Mnth 
$sql = "SELECT COUNT(*) FROM usersonline WHERE lastOnline > $last1Mnth"; 
while($rows = mysql_fetch_array(mysql_query($sql))) { 
    echo "Users online in the last month: " . $rows['COUNT(*)'] . "<br /><br />\n"; 
} 

Wenn es eine effizientere Art und Weise ist, diese Daten zu präsentieren, I Ich möchte es erweitern, um nicht nur zu zeigen, wie viele Nutzer für jede dieser Messwerte auf meiner gesamten Website online sind, sondern die Daten für jede Seite meiner Website aufzuzeichnen und auszugeben.

Antwort

4
SELECT 
    SUM(lastOnline <= 60) AS one_minute, 
    SUM(lastOnline <= 300) AS five_minutes, 
    ... 
    SUM(lastOnline <= 30240000) AS one_month 
FROM usersonline 

Mit dieser Methode können Sie alles, was Sie benötigen, in einer einzigen Abfrage mit einem einzigen Tabellenscan erhalten; es wird nicht viel effizienter. Wie andere bereits erwähnt haben, sollten Sie das Ergebnis zwischenspeichern, da es relativ teuer ist (selbst in dieser optimierten Form). Es hat keinen Sinn, dies bei jedem Seitenladen zu berechnen, besonders wenn Sie mehrere Treffer pro Sekunde sehen (was sehr wahrscheinlich ist, wenn Sie beispielsweise die erste Seite von digg aufrufen)

lastOnline < = 60 ergibt 1 für Zeilen, in denen die Bedingung wahr ist, und 0 für Zeilen, in denen die Bedingung falsch ist; SUM() summiert diese 1 und Nullen und gibt Ihnen die Anzahl der Zeilen, für die die Bedingung erfüllt ist.

Diese Technik wurde vor ein paar Jahren aus einem Benutzerkommentar in den mysql-Dokumenten gelernt; Es gibt similar examples elsewhere

+0

Ja, das war, was ich für einen einzigen Datenbankaufruf wollte, aber wie Sie sagen, würde direkt mit einem Cron-Job und Cache verwendet werden. –

0

Anstatt die Datenbank für jede dieser Zeiten aufzurufen, können Sie alle innerhalb des letzten Monats anrufen und nach Datum sortieren. Dann können Sie in php Datum und Uhrzeit vergleichen, um zu sehen, wie lange sich der Benutzer zuletzt angemeldet hat.

+0

Das scheint eine unkomplizierte Lösung zu sein, aber was wäre ein effizienter Weg, um jeden Datensatz durchzugehen, um ihn in die verschiedenen Metriken zu sortieren? Wäre es immer noch in Ordnung, 100.000 Datensätze zu durchlaufen? –

+1

Der Nachteil der Arbeit in PHP ist, dass Sie mit der Übertragung all dieser Daten in PHP über einen Socket umgehen müssen; oft kann diese Datenübertragung für große Datenmengen ziemlich teuer sein. Wenn Sie Ihre Datenbank dazu bringen können, die Berechnungen für Sie durchzuführen und die Ergebnisse zurückzugeben, sparen Sie viel Kommunikationsaufwand. –

+0

Sie müssen nicht wirklich jeden Datensatz vergleichen. Sie können eine binäre Suche verwenden, um zu ermitteln, wo sich der Unterbrechungspunkt für die einzelnen Zeiten befindet, die Sie anzeigen möchten. –

3

Richten Sie einen Cron-Job ein, der die korrekten Werte nur einmal pro Minute/5 Minuten usw. berechnet. Zwischenspeichern Sie das Ergebnis und zeigen Sie es stattdessen an. Es gibt wirklich keine Notwendigkeit, diese Art von Statistiken X-mal pro Sekunde zu berechnen, wenn sie sich nur einmal pro Minute oder einmal alle halbe Stunde ändern.

+0

Das ist ein guter Punkt und konzentriert sich auf regelmäßige Anrufe statt für jeden Besuch, der Tausende sein könnte, so einfach hätte ich daran denken sollen. –

0

Wenn Sie Ihre Sitzungen in Dateien speichern, können Sie die Anzahl der Dateien zählen, auf die in einem bestimmten Zeitraum zugegriffen wurde. Dann würde es überhaupt keinen Datenbankzugriff geben.

+0

Wäre eine einzelne Protokolldatei besser?Im Laufe der Zeit scheint es unübersichtlich zu sein, 100.000 Session-Dateien zu haben. –

+0

Ja, aber PHP verwaltet diese Dateien und löscht sie, sobald die Sitzung abgelaufen ist. – psayre23

+0

Das ist eine faire Lösung, um zu sehen, wer jetzt online ist, aber separate Sitzungsdateien müssten dann erstellt werden, um jede Metrik abzudecken, wo Sitzungen 1min, 5min, 1hr, 1Tag, 1Monat etc. –

Verwandte Themen