Matthias: Wie wird das Programm schneller ?

Hallo,

folgende Situation macht mir Ärger:

In einer WAMP-Installation sorgen PHP-Skripte dafür, das Kundendaten in der Mysql-Datenbank gespeichert und verarbeitet werden.

Mittlerweile gibt es rund 1,7 Millionen Datensätze und eine Verarbeitung über die komplette Tabelle (130 MB) dauert ca. 3 Stunden [ O(n²) leider ].
Eine SQL-Abfrage via phpmyadmin, die mir die gesamte Tabelle wiedergeben würde dauert 3 Minuten.

Meine Frage:
Wäre es vom Vorteil, wenn ich das Programm statt in PHP, z.B. in Java schreibe?

  1. Meine Frage:
    Wäre es vom Vorteil, wenn ich das Programm statt in PHP, z.B. in Java schreibe?

    Ich glaube nicht, dass das die Performance steigern würde(eher verschlechtern :->).

    Um wirklich die Performance zu steigern, solltest du bei der Datenbank tunen. Zum Beispiel Indeze setzen. Bei Spalten, die oft in der where Klausel eines SQL statements vorkommen, sollte man einen index setzen. Wenn du viele Joins hast (eine abfrage auf mehrere tabellen), sollte man sich überlegen, die Daten redundat (Daten in einer tabelle)zu speichern. Dafür erhöht man aber die Perfomance bei Leseaktivitäten gewaltig.

    Eine anderer Programmiersprache würde die Performance meiner Meinung nach nicht erhöhen.

    MFG Irki

    1. Hello,

      Meine Frage:
      Wäre es vom Vorteil, wenn ich das Programm statt in PHP, z.B. in Java schreibe?

      Welcher Teil der Verarbeitung schluckt denn die Zeit? Sind es die Datenbank-Operationen oder sind es die PHP-Teile?

      Ich vermute, dass man da über die Systemeinstellungen der MySQL-Datenbank eine Menge beschleunigen kann. Wie groß ist denn der eingestellte Speicher pro Request in der my.cnf? Standard sind 8MB, was für 1,7 Millionen Datensätze bestimmt nicht ausreicht. Alleine eine Indextabelle auf den Primary Key würde da schon 27MB benötigen. Ein 'Order by' würde also richtig kraft kosten. Zwischendurch wird swapped, was das Zeug hält.

      Setze den Speicher auf 64MB hoch und du müsstest, was MySQL betrifft eine Steiferung von mindestens Faktor 10 verspüren.

      Das ist natürlich in keiner Weise wissenschaftlich abgesichert [ O(n²) ] aber in der Praxis erprobt. Vieleicht reicht das ja auch für den Anfang.

      Liebe Grüße aus http://www.braunschweig.de

      Tom

      --
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
      Nur selber lernen macht schlau
      1. Hallo,

        den Hauptteil der Arbeit trägt PHP, es gibt nur 2 Abfragen und das sind die selben wie per Hand in phpmyadmin getestet.

        Die Verarbeitung schluckt halt so viel Zeit, dabei gibt es eigentlich nur 2 verschatelte for-Schleifen. Jedes Ergebnis wird in einem Array gesammelt und dieses würde dann nachher in eine Tabelle in die DB geschrieben, aber soweit bin ich halt noch nicht.

        Grüße, Matthias

        1. Hello,

          Die Verarbeitung schluckt halt so viel Zeit, dabei gibt es eigentlich nur 2 verschatelte for-Schleifen. Jedes Ergebnis wird in einem Array gesammelt und dieses würde dann nachher in eine Tabelle in die DB geschrieben, aber soweit bin ich halt noch nicht.

          Also ein

          insert into $ziel ($target_fieldlist) select ($src1_fieldlist) from $src1;

          dass Du da "zu Fuß" mit PHP aufbaust, oder?

          Liebe Grüße aus http://www.braunschweig.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          Nur selber lernen macht schlau
          1. Hallo

            Die Verarbeitung schluckt halt so viel Zeit, dabei gibt es eigentlich nur 2 verschatelte for-Schleifen. Jedes Ergebnis wird in einem Array gesammelt und dieses würde dann nachher in eine Tabelle in die DB geschrieben, aber soweit bin ich halt noch nicht.

            Also ein

            insert into $ziel ($target_fieldlist) select ($src1_fieldlist) from $src1;

            Nein, vielmehr ein insert into tab3 (a,b,c,...) values ("a","b",....) . Wenn ich die Werte eh so kompliziert aus den for-Schleifen rausziehen muss, dann kann ich sie auch direkt in das Array speichern.

      2. Hallo

        Wie groß ist denn der eingestellte Speicher pro Request in der my.cnf? Standard sind 8MB, was für 1,7 Millionen Datensätze bestimmt nicht ausreicht. Alleine eine Indextabelle auf den Primary Key würde da schon 27MB benötigen. Ein 'Order by' würde also richtig kraft kosten. Zwischendurch wird swapped, was das Zeug hält.

        ist das der Eintrag:

        set-variable    = myisam_sort_buffer_size=8M    ?

        kann ich sonst noch was in der conf verbessern ?

        _____________________________________________________________________

        The MySQL server

        [mysqld]
        port            = 3306
        socket          = C:/xampp/mysql/mysql.sock
        skip-locking
        set-variable    = key_buffer=16M
        set-variable    = max_allowed_packet=1M
        set-variable    = table_cache=64
        set-variable    = sort_buffer=512K
        set-variable    = net_buffer_length=8K
        set-variable    = myisam_sort_buffer_size=64M
        log-bin
        server-id       = 1

        basedir=C:/xampp/mysql
        tmpdir=C:/xampp/tmp
        datadir=C:/xampp/mysql/data

        #bind-address=192.168.1.1
        #log-update     = /path-to-dedicated-directory/hostname

        Uncomment the following if you are using BDB tables

        #set-variable   = bdb_cache_size=4M
        #set-variable   = bdb_max_lock=10000

        skip-innodb

        Uncomment the following if you are using InnoDB tables

        #innodb_data_home_dir = C:/xampp/mysql/
        #innodb_data_file_path = ibdata1:10M:autoextend
        #innodb_log_group_home_dir = C:/xampp/mysql/
        #innodb_log_arch_dir = C:/xampp/mysql/

        You can set .._buffer_pool_size up to 50 - 80 %

        of RAM but beware of setting memory usage too high

        #set-variable = innodb_buffer_pool_size=16M
        #set-variable = innodb_additional_mem_pool_size=2M

        Set .._log_file_size to 25 % of buffer pool size

        #set-variable = innodb_log_file_size=5M
        #set-variable = innodb_log_buffer_size=8M
        #innodb_flush_log_at_trx_commit=1
        #set-variable = innodb_lock_wait_timeout=50

        [mysqldump]
        quick
        set-variable    = max_allowed_packet=16M

        [mysql]
        no-auto-rehash

        Remove the next comment character if you are not familiar with SQL

        #safe-updates

        [isamchk]
        set-variable    = key_buffer=20M
        set-variable    = sort_buffer=20M
        set-variable    = read_buffer=2M
        set-variable    = write_buffer=2M

        [myisamchk]
        set-variable    = key_buffer=20M
        set-variable    = sort_buffer=20M
        set-variable    = read_buffer=2M
        set-variable    = write_buffer=2M

        [mysqlhotcopy]
        interactive-timeout
        ____________________________________________________________________

        Grüße, Matthias

        1. Hello,

          bevor ich jetzt hastig-hastig was verkürztes oder falsches sage....
          Es ist schon etwas komplexer, als man in einem Satz erklären kann.

          Lies Dir mal http://dev.mysql.com/doc/mysql/de/Option_files.html durch und dann die Beispiel-Konfigurationen, die Du wahrscheinlich auf Deinem Server unter

          /usr/local/mysql/support-files/my-huge.cnf
                                           my-large.cnf
                                           my-medium.cnf
                                           my-small.cnf

          findest.

          Wenn Du die Beispeile dort vergleichst, müsste es eigentlich klarer werden, als wenn ich lange rede.

          Liebe Grüße aus http://www.braunschweig.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          Nur selber lernen macht schlau
          1. Hello,

            mit 'show variables;'

            kannst Du die aktuell für den User geltenden Einstellungen abfragen.

            Liebe Grüße aus http://www.braunschweig.de

            Tom

            --
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            Nur selber lernen macht schlau
  2. Hi,

    Mittlerweile gibt es rund 1,7 Millionen Datensätze und eine Verarbeitung über die komplette Tabelle (130 MB) dauert ca. 3 Stunden [ O(n²) leider ].

    die Frage ist doch: was willst Du eigentlich tun? Eventuell kann man ja die Skriptimplementierung verbessern, sodaß die Performance besser wird. Dafür bräuchten wir aber Codebeispiele.

    Eine SQL-Abfrage via phpmyadmin, die mir die gesamte Tabelle wiedergeben würde dauert 3 Minuten.

    Wie? Die selbe Abfrage wie in Deinem eigenen Skript?

    Wäre es vom Vorteil, wenn ich das Programm statt in PHP, z.B. in Java schreibe?

    Das glaube ich kaum. Eine Performancesteigerung wäre nur gegeben, wenn die Ausführungszeit hauptsächlich durch die PHP-Engine verursacht würde. So wie es sich aber darstellt, braucht die Datenbank so lange um die Abfrage zu bearbeiten.

    viele Grüße
      Achim Schrepfer

    --
    http://reskit.speedesign.de/ - PHP-Bibliothek zum automatischen Erzeugen von HTML-Tabellen, -Formularen und -Baummenüs anhand von MySQL-Tabellen
    Selfcode: sh:) fo:| ch:| rl:° br:> n4:{ ie:% mo:} va:| de:< zu:| fl:( ss:) ls:& js:|
    1. Hallo,

      erstmal Danke für die Antworten.

      Es sieht so aus, das ich zwei Tabellen habe die ich miteinander verknüpfen muss, damit diese eine große bilden.

      Die Abfrage per SQL in phpmyadmin dauert wie gesagt nur 3 Minuten,

      die Verarbeitung mit PHP, also das zusammenführen dauert rund 3 Stunden. Damit ist wirkliche Rechenzeit gemeint, da es nur 2 mysql_query's gibt, nämlich dieselben wie oben mit der Hand in phpmyadmin eingegeben.

      Die Tabellen werden in 2 Arrays gespeichert und mit for-Schleifen zusammengeführt, leider ist dabei eine doppelte for-Schleife nötig, da es keinen Schlüssel, bzw. keinen Fremdschlüssel gibt.
      Die Tabellen lassen sich trotzdem durch einen Umweg zusammenführen, nur sind dafür leider 2 geschachtelte for-Schleifen nötig.

      Grüße, Matthias

      1. Hello,

        Die Tabellen werden in 2 Arrays gespeichert und mit for-Schleifen zusammengeführt, leider ist dabei eine doppelte for-Schleife nötig, da es keinen Schlüssel, bzw. keinen Fremdschlüssel gibt.
        Die Tabellen lassen sich trotzdem durch einen Umweg zusammenführen, nur sind dafür leider 2 geschachtelte for-Schleifen nötig.

        Das Zusammenführen lässt sich doch bestimmt auch mittels SQL erledigen?

        Liebe Grüße aus http://www.braunschweig.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
  3. Hi,

    mit Java wirds wohl nicht viel schneller, denn nicht PHP erledigt die Hauptarbeit, sondern die DB-Engine. Versuche die DB-Strukturen weiter zu optimieren (Schlüssel, Index) und vor allem die SQL-Statements optimaler zu formulieren, bzw. zu optimieren. Wie sehen denn die Befehle aus?

    MfG
    Danny