Helmut Weber: (MYSQL) Auswertung der Datenbank

Hallo SelfForum,

ich muss eine Datenbank auswerten, in der ca. 500.000 Einträge stehen.
Hier mein Quellcode:
my $year  = $CGI->param('year');
my $month = $CGI->param('month');

my $entrys_month = $Config::DBH->selectrow_array( "SELECT COUNT(entry) FROM participant WHERE year(entry) = $year AND MONTH(entry) = $month " );

my @monatsliste = ();
  for ( my $i = 1; $i <= 31; $i++) {
    my $entrys = $Config::DBH->selectrow_array( "SELECT COUNT(entry) FROM participant WHERE YEAR(entry) = $year AND MONTH(entry) = $month AND DAYOFMONTH(entry) = $i " );
    push @monatsliste, { VALUE => $i, ENTRYS => $entrys };
  }

Ich möchte Auswerten, an welchem Tag im Monat wieviele Eintragungen gemacht worden sind, und diese per HTML anzeigen.
Mein Problem ist, das ich an die Grenze der maximalen Bearbeitungszeit komme, und das Skript abgebrochen wird. (Weit über 1 Minute).

Kann mir jemand einen Tipp geben, wie ich meine SQL-Abfrage optimieren kann?

Gruß
Helmut Weber

--
-------------------------------------------
Mode ist eine Variable, Stil eine Konstante
  1. Halihallo Helmut

    Kann mir jemand einen Tipp geben, wie ich meine SQL-Abfrage optimieren kann?

    Benutzt du Indizies? - Wenn nein, hurtig, hurtig einen definiert und staunend über die
    Abfragegeschwindigkeit.

    Viele Grüsse

    Philipp

    --
    RTFM! - Foren steigern das Aufkommen von Redundanz im Internet, danke für das lesen der Manuals.
    Selbstbedienung! - Das SelfForum ist ein Gratis-Restaurant mit Selbstbedienung, Menüangebot steht in den </faq/> und dem </archiv/>.
    1. Hallo Philipp,

      Benutzt du Indizies? - Wenn nein, hurtig, hurtig einen definiert und staunend über die
      Abfragegeschwindigkeit.

      Danke  für den Tipp!
      Heißt das für mich, das ich für die Spalte "entry" einen Index anlegen muss und schon wird meine Abfragegeschwindigkeit besser?
      Bisher hatte ich nur einen Index für die ID-Nummer des Eintrages (PRIMARY), wird aber für meine Abfrage nicht von Bedeutung sein.

      Ich werde es mal ausprobieren...

      Gruß
      Helmut Weber

      --
      -------------------------------------------
      Mode ist eine Variable, Stil eine Konstante
      1. Halihallo Helmut

        Danke  für den Tipp!

        Dass du den ja nie vergisst, der ist nämlich _zentral_ für Datenbanksysteme.

        Heißt das für mich, das ich für die Spalte "entry" einen Index anlegen muss und schon wird meine Abfragegeschwindigkeit besser?

        Exakt.

        Bisher hatte ich nur einen Index für die ID-Nummer des Eintrages (PRIMARY), wird aber für meine Abfrage nicht von Bedeutung sein.

        Ein Index auf den Primary bringt dir bei diese(r|n) Abfrage(n) gar nichts.

        Viele Grüsse

        Philipp

        --
        RTFM! - Foren steigern das Aufkommen von Redundanz im Internet, danke für das lesen der Manuals.
        Selbstbedienung! - Das SelfForum ist ein Gratis-Restaurant mit Selbstbedienung, Menüangebot steht in den </faq/> und dem </archiv/>.
  2. Halihallo Helmut

    my @monatsliste = ();
      for ( my $i = 1; $i <= 31; $i++) {
        my $entrys = $Config::DBH->selectrow_array( "SELECT COUNT(entry) FROM participant WHERE YEAR(entry) = $year AND MONTH(entry) = $month AND DAYOFMONTH(entry) = $i " );
        push @monatsliste, { VALUE => $i, ENTRYS => $entrys };
      }

    Tipp nummero dos:
    Verwende GROUP BY MONTH(entry), YEAR(entry), DAYOFMONTH(entry)
    und lass die for-Schleife im Script weg. Damit reduziert sich die Anzahl der Abfragen auf
    zwei statt 32.

    Viele Grüsse

    Philipp

    --
    RTFM! - Foren steigern das Aufkommen von Redundanz im Internet, danke für das lesen der Manuals.
    Selbstbedienung! - Das SelfForum ist ein Gratis-Restaurant mit Selbstbedienung, Menüangebot steht in den </faq/> und dem </archiv/>.
    1. Halihallo Philipp

      my @monatsliste = ();
        for ( my $i = 1; $i <= 31; $i++) {
          my $entrys = $Config::DBH->selectrow_array( "SELECT COUNT(entry) FROM participant WHERE YEAR(entry) = $year AND MONTH(entry) = $month AND DAYOFMONTH(entry) = $i " );
          push @monatsliste, { VALUE => $i, ENTRYS => $entrys };
        }
      Verwende GROUP BY MONTH(entry), YEAR(entry), DAYOFMONTH(entry)

      Korrektur: MONTH(entry) und YEAR(entry) gehören in die WHERE-Klausel, da sie staatischer
      Natur sind (sie werden ja als Parameter des Scripts festgelegt). Bei meinem Vorschlag
      hättest du jeden Tag einzeln, egal in welchem Jahr und Monat aufgelistet bekommen, dir
      beliebt es ja nur nach dem Monat und Jahr, welche übergeben wurden.

      Zudem wäre es ggf. sogar performanter, wenn du die einzelnen Tage aufsummierst und so die
      Totale Anzahl Einträge für den gesamten Monat berechnest. So würde die Anzahl der
      Abfragen auf eins reduziert und die Berechnung der ersten Query-Abfrage auf das
      addieren von 31 Werten reduziert. Ob sich das jedoch lohnt oder nicht müsstest du mit
      Benchmarks messen.

      btw: was haben Datenbanken mit Perl zu tun?

      Viele Grüsse

      Philipp

      --
      RTFM! - Foren steigern das Aufkommen von Redundanz im Internet, danke für das lesen der Manuals.
      Selbstbedienung! - Das SelfForum ist ein Gratis-Restaurant mit Selbstbedienung, Menüangebot steht in den </faq/> und dem </archiv/>.