MightyMike: MySQL/PHP-Besucherzähler Performance

Hi zusammen,

ich habe für meine Seite einen MySQL/PHP-Zähler realisiert. Da ich ein wenig Info über meine Besucher sammlen möchte, speichere ich in einer Tabelle, wo die Leute herkommen und den Zeitpunkt ihres Besuchs. So weit so gut, spielt eigentlich auch keine Rolle.

Jedenfalls hole ich mir aus dieser Tabelle, die Gesamtzahl der Besucher, in dem ich mit einer MySQL-Abfrage einfach die Zahl der Zeilen in der Tabelle auslese. Deswegen meine Frage, ob das so auf Dauer schlecht für die Performance der Seite ist?! Ich habe jetzt nicht so die hammermäßig stark frequentierte Seite (so zwischen 10 und 30 Besucher am Tag) und deswegen ist das momentan eh nicht das Problem. Aber wie sieht das aus, wenn die Tabelle mal zehntausende von Einträgen hat/haben sollte. Ist so ein Zähler dann überhaupt noch "schnell genug"?

Grüße
Mighty

  1. Hi,

    irgenwann wird das die performanze drücken, aber Du hast ja die Möglichkeit einen sinnvollen Index auf die Tabelle anzulegen.

    Noch ne Idee (so mach ichs): Lass den Zähler über Ajax laufen. Damit läuft der Zählprozess asynchron, also völlig abgekoppelt vom Request der Seite und somit gibts keine Perf.einbußen.

    Eine andere Möglichkeit ist die, den Zählprozess als Child mit fork abzukoppeln, der Parent schickt einen gültigen Header und ein OK und der Child kann in aller Ruhe mit der DB arbeiten.

    --roro

    1. yo,

      irgenwann wird das die performanze drücken, aber Du hast ja die Möglichkeit einen sinnvollen Index auf die Tabelle anzulegen.

      ein index bringt gar nicht, bezüglich des zählers. eventuell könnte man den zähler als textdatei abspeichern bei jedem zugriff um eins erhöhen. aber bei den datenvolumen von dem du gesprochen hast sollte ein COUNT(*) doch recht schnell ausgeführt werden. einfach an der konsole ausborbieren mit testdaten.

      Ilja

      1. Hai;

        ein index bringt gar nicht, bezüglich des zählers. eventuell [..]

        kommt drauf an, wie der Zähler arbeitet. Wenn die WHERE Klausel angewandt wird, um für einen bestimmten Record den Zähler hochzusetzen bringt das auf jeden Fall was (Index auf Titel oder Seitenadresse).

        Wenn nur INSERTs gemacht werden brauchts keinen Index, da hast Du schon recht. Den brauchts eher bei der Auswertung und Erstellung von Statistiken.

        --roro

        1. yo,

          ein index bringt gar nicht, bezüglich des zählers. eventuell [..]

          kommt drauf an, wie der Zähler arbeitet.

          wenn du diesen satz angeschaut hättest "in dem ich mit einer MySQL-Abfrage einfach die Zahl der Zeilen in der Tabelle auslese", dann wäre auch klar, das in diesem falle ein index nichts bringen kann.

          Ilja

      2. eventuell könnte man den zähler als textdatei abspeichern bei jedem zugriff um eins erhöhen.

        Habe ich auch schonmal gemacht. Allerdings hatte ich hier das Problem, dass ich auch eine Tagesbesucheranzeige habe. Dann müßte ich also eine zweite Zahl in die Datei schreiben. Aber wie entscheide ich dann, ob gerade, wenn ein neuer Besucher auf die Seite gekommen ist, ein neuer Tag begonnen hat? Also muß noch ein Datum mit rein.

        Die Lösung mit der Tabelle schien mir insgesamt am elegantesten, um nicht auf mehrere Sachen gleichzeitig zugreifen zu müssen. Aber ich lasse mich gerne eines besseren belehren.

        1. yo,

          Habe ich auch schonmal gemacht. Allerdings hatte ich hier das Problem, dass ich auch eine Tagesbesucheranzeige habe. Dann müßte ich also eine zweite Zahl in die Datei schreiben. Aber wie entscheide ich dann, ob gerade, wenn ein neuer Besucher auf die Seite gekommen ist, ein neuer Tag begonnen hat? Also muß noch ein Datum mit rein.

          es gibt sicherlich viele lösungen, die mit den logs gefällt mir grundsätzlich deswegen am besten, weil du nihcts zusätzlich speichern musst, sondern nur noch auswerten.

          falls die logs nichts für dich sind, dann könnte man den tageszähler auch so implementieren, dass das aktuelle datum in der datei selbst abgespeichert wird. sprich für jeden tag wird eine andere datei genommen, was den tageszähler betrifft, falls die diese aufheben willst.

          oder aber du speicherst immer nur das letzte datum mit in die datei ab. und wenn das aktuelle und das in der datei sich unterscheiden, dann "nullst" du den zähler wieder, bzw. setzt ihn auf 1. dann hättest du wieder nur eine datei mit den gesamtzähler, tageszähler und datum des letzten zugriffs.

          Ilja

          1. hi,

            es gibt sicherlich viele lösungen, die mit den logs gefällt mir grundsätzlich deswegen am besten, weil du nihcts zusätzlich speichern musst, sondern nur noch auswerten.

            Mein Provider gibt mir jeden Monat ein neues Log ;-)

            Ich meine, ein Zähler auf LogFile - Basis ist keine so gute Idee. Eine DB wie MySQL ist da schon ok. Das gibt eine geordnete und scalierbare Datenhaltung.

            Und mit Dateien, hats immer noch die Thematik mit race conditions... andererseits gibts auch in MySQL ein Transaktionskonzept, was mir die Arbeit abnimmt.

            --roro

    2. Hi,

      irgenwann wird das die performanze drücken, aber Du hast ja die Möglichkeit einen sinnvollen Index auf die Tabelle anzulegen.

      Noch ne Idee (so mach ichs): Lass den Zähler über Ajax laufen. Damit läuft der Zählprozess asynchron, also völlig abgekoppelt vom Request der Seite und somit gibts keine Perf.einbußen.

      Eine andere Möglichkeit ist die, den Zählprozess als Child mit fork abzukoppeln, der Parent schickt einen gültigen Header und ein OK und der Child kann in aller Ruhe mit der DB arbeiten.

      --roro

      Ajax? fork?
      Ich glaube, so weit fortgeschritten bin ich dann glaube ich doch noch nicht :o).

  2. Hi,

    ich habe für meine Seite einen MySQL/PHP-Zähler realisiert.

    warum? Hast Du keinen Zugriff auf die Serverlogs? Dort stehen i.d.R. alle relevanten Daten bereits drin und müssen nur noch ausgewertet werden.

    freundliche Grüße
    Ingo

    1. Hi,

      ich habe für meine Seite einen MySQL/PHP-Zähler realisiert.
      warum? Hast Du keinen Zugriff auf die Serverlogs? Dort stehen i.d.R. alle relevanten Daten bereits drin und müssen nur noch ausgewertet werden.

      freundliche Grüße
      Ingo

      Auch das ist klar, dass ich das machen könnte. Aber das habe ich bewußt nicht gewählt. Ich gehe am Tag bestimmt ne halbe Million mal auf die Seite und will nicht mitgezählt werden, weswegen ich mir bei meinem eigenen Zähler auch ein Hintertürchen eingebaut habe, um eben das selbst zählen zu vermeiden. Ausserdem weiß ich auch nicht, wie das bei Serverlogs mit einer Reloadsperre ist.

      1. Hi,

        Ich gehe am Tag bestimmt ne halbe Million mal auf die Seite und will nicht mitgezählt werden, weswegen ich mir bei meinem eigenen Zähler auch ein Hintertürchen eingebaut habe, um eben das selbst zählen zu vermeiden.

        Da Du Dir die Serverlogs bestimmt nicht als ASCII-Files im Texteditor ansehen willst, ist das kein Problem. Du mußt bei der Auswertung lediglich Deine eigenen zugriffe erkennen und rausfiltern. Ich mache das bei meiner Seite mit meinem Auswertungsprogramm auch. Zur Erkennung habe ich den UserAgent-String meiner Browser manpuliert.

        Ausserdem weiß ich auch nicht, wie das bei Serverlogs mit einer Reloadsperre ist.

        Sowas muß doch das Auswertungsprogramm erledigen. Genauso wie Du die Einträge in die Datenbank filterst muß das Auswertungsprogramm aus den Logeinträgen diejenigen von vermutlich gleichen Besuchern filtern.

        freundliche Grüße
        Ingo

  3. Hi Mighty

    Tabelle Besucherzaehler

    Anz_besucher      number;

    insert into Besucherzaehler (Anz_besucher) values (0);

    Und bei jedem Besuch:

    update Besucherzaehler set Anz_besucher=Anz_besucher+1;
    commit;

    Und bei jedem Anzeigen der Besucher:

    select Anz_besucher from Besucherzaehler;

    Gruß

    Hans

    1. Hi Mighty

      Tabelle Besucherzaehler

      Anz_besucher      number;

      insert into Besucherzaehler (Anz_besucher) values (0);

      Und bei jedem Besuch:

      update Besucherzaehler set Anz_besucher=Anz_besucher+1;
      commit;

      Und bei jedem Anzeigen der Besucher:

      select Anz_besucher from Besucherzaehler;

      Gruß

      Hans

      Prinzipiell klar. Die Lösung hatte ich auch schonmal. Aber dann habe ich andererseits immer zwei Tabellen, auf die ich zugreife, wenn ein neuer Besucher auf die Seite kommt. Fand' ich jetzt nicht so elegant. Stellt sich halt wieder die gleiche Frage: Was ist schneller? Eine Tabelle mit (irgendwann mal) ner Menge Daten oder Zugriff auf zwei Tabellen...

      1. Hi !

        Prinzipiell klar. Die Lösung hatte ich auch schonmal. Aber dann habe ich andererseits immer zwei Tabellen, auf die ich zugreife, wenn ein neuer Besucher auf die Seite kommt. Fand' ich jetzt nicht so elegant. Stellt sich halt wieder die gleiche Frage: Was ist schneller? Eine Tabelle mit (irgendwann mal) ner Menge Daten oder Zugriff auf zwei Tabellen...

        Naja, dann kannst Du ja einen Trigger auf die Tabelle mit den User-Daten machen, die die Anzahl der Besucher in der zweiten Tabelle hochzählt.

        Gruß

        Hans