Zeitproblem - Abfragen sind zu langsam

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Zeitproblem - Abfragen sind zu langsam

    Mit nachfolgender Abfrage ermittele ich alle Kunden, deren Erstkontakt in dem Zeitraum vor 60 und 45 Tagen lag.

    $result=mysql_query("select * from $tabelle where ((Erstkontakt >= CURDATE() -INTERVAL 60 DAY) and (Erstkontakt <= CURDATE() - INTERVAL 45 DAY))");

    Diese Kunden nehme ich für nachfolgende Selektion:

    while ($row = mysql_fetch_array($result)) {
    $resultselection=mysql_query("select $tabelle1.*, $tabelle2.* from $tabelle1, $tabelle2 WHERE ($tabelle2.ObjArt like '%" . $row['Objekttyp'] . "%') and .......");

    und gebe die Resultate in nachfolgender Tabelle aus:

    while ($rowselection = mysql_fetch_array($resultselection)) {
    /* AUSGABE DER ERGEBNISSE in Tabelle */
    echo "<tr><TD align=left>" . $rowselection['KdNr'] . "</TD>";
    .....

    Jetzt habe ich das Problem, daß diese Abfragen sehr lange dauern und Gefahr gehe, daß das Skript aufgrund des Time-limits in Apache-Konfiguration abgebrochen wird (30 Sekunden).

    Gibt es eine bessere Abfrageart, die schneller geht, oder wie kann ich diese Abfrage optimieren?

  • #2
    Tja

    Die Performance ist abhängig vom Aufbau der Tabellen mit ihren Relationen, den gesetzten Indizes, den Datenbank Parametern, der Datenmenge uvm.

    So auf die Schnelle ohne sich ein genaues Bild zu machen zu können ist das etwas schwierig - Schau Dir mal das Kapitel MySQL OPTIPMIZATION an: http://www.mysql.com/documentation/m...L_Optimisation

    Ich glaube als Erstes kannst Du beim LIKE ansetzen
    PHP-Code:
    ... $tabelle2.ObjArt like '%" . $row['Objekttyp'] . "%' 
    Kann man das nicht irgendwie in eine = Bedingung umwandeln?

    Vielleicht kann man diese LIKE Bedingung ganz ans Ende setzen, das kommt natürlich drauf an. Die erste angegebene Bedingung sollte bereits die meisten Einschränkungen erledigt haben.
    Die weiteren Bedingungen die via AND drangehängt werden selektieren nur mehr aus den bereits zuvors elektierten Records.

    Wenn natürlich dieses LIKE schon das größte Stück eliminiert wird's schon OK sein. Wie die Daten aufgebaut sind und die Inhalte aussehen weißt Du ja.

    Eine Abfrage läuft dann gut, wenn über das abgefragte Kriterium ein Index gelegt wurde. Also über ObjArt.

    Wenn Du den LIKE wegbekommen könntest, dann glaube ich ist schon ein großer Brocken erledigt. Mitunter ist dafür vielleicht auch die Datenstruktur zu ändern. Das kann sich aber bezahlt machen.

    Also ich tu mir schwer Dir weitere Tipps zu geben, aber vielleicht kannst Du ja mit dem einen oder anderen Anstatz was anfangen.
    Zuletzt geändert von hand; 12.07.2002, 18:11.

    Kommentar


    • #3

      Kannst Du mal das komplette Statement posten ... nur um sicherzugehen das es kein Kartesisches Produkt wird??

      PS.: LIKE ist ganz suboptimal da in diesem Falle kein Index verwendet wird ... außerdem sollte man die Klammerungen nach Möglichkeit weglassen da sonst der Interne Optimizer beeinträchtigt ist ...

      Schau dir das Statement mal mit: EXPLAIN statement an ... da kannst Du erkennen welche Indizes, wie verwendet werden ...

      Ansonsten folge hands Worten ... immer schon indizieren ...
      carpe noctem

      [color=blue]Bitte keine Fragen per EMail ... im Forum haben alle was davon ... und ich beantworte EMail-Fragen von Foren-Mitgliedern in der Regel eh nicht![/color]
      [color=red]Hinweis: Ich bin weder Mitglied noch Angestellter von ebiz-consult! Alles was ich hier von mir gebe tue ich in eigener Verantwortung![/color]

      Kommentar


      • #4
        Ein bisschen könnten auch CURDATE und INTERVAL mit reinspielen, mach das doch mit PHP, am besten mit Timestamps, weil das ein einfacher Zahlenvergleich ist. Am besten installierst Du einen Timer und schaust welche Optimierung wie viel bringt.

        Kommentar


        • #5
          Der erste Teil mit curdate() wird nur einmal exekutiert. Wenn das Resultat aber viele viele Erstkontakte ergibt werden in der Folge viele viele Selects gegen die Datenbank abgesetzt und das ist das Problem.

          Wenn ich so durchlese, was ich oben geschrieben habe könnte ich bei einigen Dingen sagen - "ja aber". Das mit den Indizes ist schon richtig, werden aber wieder zuviele Indizes angelegt kann das unter bestimmten Umständen, bei Inserts und Updates beispielsweise auch wieder Performanceprobleme zur Folge haben.

          Optimieren fängt bereits bei der Auswahl des Spaltentyps an
          o CHAR Felder können viel schneller verarbeitet werden als VARCHAR.
          o NOT NULL Deklaration unterstützen schnellere Verarbeitung
          o ENUM bei begrenzt unterschiedlichen Inhalten
          o PROCEDURE ANALYSE() hilft bei der Analyse der Spalten
          o OPTIMIZE TABLE anwenden, wenn Inhalte oft verändert werden
          o Die Suche in BLOB- oder TEXT-Feldinhalten sollte man tunlichst vermeiden

          o Bei Feldinhaltvergleichen ist es optimal wenn felder gleichen Typs miteinander verglichen werden.

          und und und ....

          Kommentar


          • #6
            @hand: Kennst Du ein gutes Tutorial zum Thema?

            Kommentar


            • #7
              Na leider nit. Aber im Buch von Paul Dubois, MySQL Entwicklung, Implementierung und Referenz, Markt und Technik Verlag, ISBN 3-8272-5793-X wird ein wenig darauf eingegangen.

              Diese Dinge folgen aber alle einer Logik. Stell Dir vor Du wärst Datenbank, wobei würdest Du Dir die Zähne ausbeißen? Und genau dort beißen sich auch die DBs die Zähne aus.

              MySQL dagegen ist von Haus aus sehr, sehr performant gegenüber anderen DBs. Vielleicht ist sie auch die schnellste. Das aber aufgrund des Umstandes, daß MySQL auf Logging-Mechanismen verzichtet, d.h. werden bei einer einer "Transaktion" viele Änderungen durchgeführt, und bei der letzten Änderung paßt was nicht, können die zuvor durchgeführten Änderungen nicht automatisch zurückgesetzt werden, was u.u. die Integrität der Relationen beeinflussen kann.

              Diese "Rollback work" Funktion ist aber tatsächlich selten in Verwendung - vorwiegend bei kritischen Applikationen wie Buchhaltungen, etc. Wenn man klever programmiert bekommt man das aber auch mit MySQL hin.

              Wenn man mit so einer DB wie MySQL auf Performancegrenzen stößt, kann man sich ausmalen, was dieselbe Applikation unter einer anderen DB anstellen würde, beispielsweise unter Oracle?

              Es gibt da ja auch noch einige Buffer an denen man drehen kann um MySQL an die Umgebung anzupassen.

              Beim Entwickeln drehe ich alles zurück, um sofort Performancegrenzen erkennen zu können. Änderungen, später in einem Produktivsystem sind obergrindig.

              Kommentar


              • #8
                vielen Dank für eure nützlichen Tips, ich trau mich gar nicht meine gesamte Abfrage zu posten, nachdem ich nun eure Bemerkungen 'nachstudiert' habe. Ich habe nämlich insgesamt 4 like - Anweisungen. Im Buch Mysql .. von Kofler wird hiervon deutlich abgeraten, da wie hand sagten u.a. auch keine Indizierung erfolgen kann. Ich denke ich werde hier ersteinmal ansetzen mit z.B. where ObjArt IN (" . $row['Objekttyp'] . ".....
                Den Tip von hand mit der Reihenfolge in den mit 'and' verbunden Where-Anweisungen hatte ich so noch gar nicht gesehen, vom Ablauf mehrer Anweisungen im Where-Bereich, sowie das mit den Klammern von goth.
                PS: im Buch von Michael Kofler, Mysql, Einführung, Programmierung und Referenz, ISBN 3-8273-1762-2, wird diese Problematik auch etwas aufgegriffen, aber nicht so im detail

                Kommentar


                • #9
                  Ich hab auch gute Erfahrungen damit gemacht, häufig abgefragte kleinere Tabellen (etwa Währungen, Länder, Shop-Produkte) am Anfang des Skripts komplett in ein Array zu ziehen. Ist natürlich Vorsicht angebracht wegen RAM-Load.

                  Kommentar


                  • #10
                    Nachtrag

                    was ich festgestellt habe ist:
                    wenn ich bei der select- Anweisung die zu selektierenden Felder genau benenne, dann laufen die Abfragen auch etwas schneller.
                    Also anstatt select * from $tabelle .. where,
                    select $tabelle.Feld1, $tabelle.Feld2 from $tabelle .... where

                    Kommentar


                    • #11
                      Das wäre mal eine Idee für einen Arbeitsuchenden mySQL-Profi: Optimierung von Datenbankstrukturen als Online-Service. Zumindest mir wäre das einige Euros Wert.

                      Kommentar

                      Lädt...
                      X