2009-02-08 30 views
5

zu implementieren Ich möchte beginnen, die Anzahl der Zeiten zu zählen, die eine Webseite angezeigt wird und benötigen daher eine Art von einfachen Zähler. Was ist die beste skalierbare Methode, dies zu tun?Was ist der beste Weg, um ein Zählerfeld in MySQL

Angenommen, ich habe eine Tabelle Frobs wobei jede Zeile zu einer Seite entspricht - einige offensichtlichen Optionen sind:

  1. Haben Sie eine unsigned int NumViews Feld in der Frobs Tabelle, die auf jede Ansicht UPDATE Frobs SET NumViews = NumViews + 1 mit aktualisiert wird . Einfach, aber nicht so gut skalieren, wie ich es verstehe.

  2. Haben Sie eine separate Tabelle FrobViews wo eine neue Zeile für jede Ansicht eingefügt wird. Um die Anzahl der Ansichten anzuzeigen, müssen Sie dann eine einfache SELECT COUNT(*) AS NumViews FROM FrobViews WHERE FrobId = '%d' GROUP BY FrobId tun. Dies beinhaltet keine Aktualisierungen, so dass Tabellensperren in MyISAM-Tabellen vermieden werden können. Die Leseleistung leidet jedoch darunter, wenn Sie die Anzahl der Ansichten auf jeder Seite anzeigen möchten.

Wie machen Sie das?

Hier gibt es einige gute Ratschläge: http://www.mysqlperformanceblog.com/2007/07/01/implementing-efficient-counters-with-mysql/ aber ich würde gerne die Ansichten der SO-Community hören.

Ich verwende InnoDb im Moment, bin aber an Antworten für InnoDb und MyISAM interessiert.

Antwort

2

Ich würde Ihren zweiten Ansatz und aggregieren Sie die Daten in die Tabelle von Ihrer ersten Lösung auf einer regelmäßigen Basis. Auf diese Weise erhalten Sie die Vorteile beider Lösungen. Um klarer zu sein: Bei jedem Treffer fügen Sie eine Zeile in eine Tabelle ein (nennen Sie sie hit_counters). Diese Tabelle hat nur ein Feld (die Seiten-ID). Alle x Sekunden führt man ein Skript (über einen Cronjob) aus, das die Daten aus der hit_counters-Tabelle zusammenfasst und in eine zweite Tabelle einfügt (man nennt sie 'hits'). Dort gibt es zwei Felder: die Seiten-ID und die Gesamttreffer.

Ich bin nicht sicher, aber imho nicht innodb Sie nicht sehr viel helfen, für Lösung 1, wenn Sie viele Treffer auf der gleichen Seite erhalten: innoDB sperrt die Zeile während so alle anderen Updates zu aktualisieren, um diese Zeile verzögert werden

Je nach. Das Programm, das in Ihnen geschrieben wurde, könnte die Updates auch zusammenstellen, indem Sie in Ihrer Anwendung zählen und die Datenbank nur alle x Sekunden aktualisieren.Dies funktioniert nur, wenn Sie eine Programmiersprache verwenden, in der Sie dauerhaften Speicher haben (wie Java Servlets, aber nicht PHP)

3

Wenn Ihnen die Skalierbarkeit wichtiger ist als die absolute Genauigkeit der Abbildungen, können Sie die Ansichtszählung in Ihrer Anwendung für kurze Zeit zwischenspeichern, anstatt die Datenbank auf jeder Seite zu treffen - z. B. nur einmal alle 100 Ansichten aktualisieren .

Wenn Ihre Anwendung zwischen Datenbankaktualisierungen abstürzt, werden Sie zwar einige Ihrer Daten verlieren, aber wenn Sie eine gewisse Ungenauigkeit tolerieren können, dann könnte dies ein nützlicher Ansatz sein.

0

Was ich mache, und es möglicherweise nicht für Ihr Szenario gilt, ist in der gespeicherten Prozedur, die die Daten vorbereitet/zurückgibt, die auf der Seite angezeigt wird, mache ich den Tabellenzähler zur gleichen Zeit aktualisiert, die es die Daten zurückgibt - Auf diese Weise gibt es nur einen Aufruf an den Server, der die Daten empfängt und den Zähler im selben Aufruf aktualisiert.

Wenn Sie keine SPs verwenden (oder wenn auf Ihrer Seite keine Datenbankdaten vorhanden sind), steht Ihnen diese Option möglicherweise nicht zur Verfügung, aber wenn Sie es sind, sollten Sie etwas beachten.

3

Das Einfügen in eine Datenbank ist nichts, was Sie auf Seitenaufrufen tun möchten. Sie werden wahrscheinlich Probleme mit der Aktualisierung Ihrer Slave-Datenbanken mit allen Einfügungen haben, da die Replikation auf MySQL mit einem einzigen Thread läuft.

In meiner Firma bedienen wir 25M Seitenaufrufe pro Tag und wir haben einen abgestuften Ansatz verfolgt.

Der View Counter wird in einer separaten Tabelle mit 2 Spalten (profileId, viewCounter) gespeichert, beide sind vorzeichenlose Integer.

Bei Artikeln, die nur selten angezeigt werden, aktualisieren wir die Tabelle in der Seitenansicht. Für häufig besuchte Artikel aktualisieren wir MySQL um 1/10 der Zeit. Für beide Arten aktualisieren wir Memcache bei jedem Treffer.
int Memcache::increment (string $key [, int $value = 1 ])

if (pageViews < 10000) { UPDATE page_view SET viewCounter=viewCounter+1 WHERE profileId = :? }

else if ((int)rand(10) == 1) { //UPDATE page_view SET viewCounter= ?:cache_value WHERE profileId = :? }

Zählung tun (*) ist sehr ineffizient in InnoDB (MyISAM hält Statistiken im Index zählen), aber MyISAM wird die Tabelle sperren auf Gleichzeitigkeit liest reduzieren. Das Ausführen eines count() für 50.000 oder 100.000 Zeilen wird sehr lange dauern. Eine Auswahl auf einem PK wird sehr schnell sein.

Wenn Sie mehr Skalierbarkeit benötigen, können Sie sich die redis

ansehen
Verwandte Themen