tester: mysqli: mehrere queries auf einmal

Hallo,

bietet mysqli in PHP die Möglichkeit, eine Vielzahl an INSERT/REPLACE queries auf einmal an den Datenbankserver zu übergeben.
Wenn ich z.B. 5000 REPLACE-Anweisungen in phpmyadmin einfüge, ist der DB-Server sehr schnell fertig.
Wenn ich aber dieselben Anweisungen mit $mysqli->multi_query($queries); do{}while($mysqli->next_result()); dauert es deutlich länger.

Was läuft hier schief oder wie geht das schneller?

Danke für Tipps

  1. Tach!

    bietet mysqli in PHP die Möglichkeit, eine Vielzahl an INSERT/REPLACE queries auf einmal an den Datenbankserver zu übergeben.

    Wenn das eine Frage sein soll, dann kennst du die Antwort offensichtlich schon: mysqli_multi_query().

    Wenn ich z.B. 5000 REPLACE-Anweisungen in phpmyadmin einfüge, ist der DB-Server sehr schnell fertig.

    Welche Extension nimmt dein PMA denn? Auf der Startseite sollte er es erzählen (wenn es nicht wegkonfiguriert wurde).

    Wenn ich aber dieselben Anweisungen mit $mysqli->multi_query($queries); do{}while($mysqli->next_result()); dauert es deutlich länger.
    Was läuft hier schief oder wie geht das schneller?

    Ich kann mir nur vorstellen, dass er die Next-Result-Schleife nicht ausführt. Bau doch mal in nicht-das-erste Statement einen Fehler ein und schau, ob der PMA den anzeigt oder nicht (nur sinnvoll, wenn er mysqli verwendet).

    Für eine Vielzahl gleichartiger Statement kann man auch Prepared Statements nehmen. Ob das allerdings schneller oder gar noch langsamer ist - schließlich hat PHP dabei viele Funktionsaufrufe auszuführen - kann ich nicht sagen.

    dedlfix.

    1. Hallo,

      danke für Deine ausführliche Antwort, der ich gleich gefolgt bin:
      -phpmyadmin nutzt die PHP Erweiterung: mysql
      -in meinem Script nutzte ich mysqli
      -die Schleife ruft next_result() für alle Queries einzeln auf, was so zu erwarten war
      -die Geschwindigkeit lässt trotzdem auch weiterhin (im Vergleich zu phpmyadmin) sehr zu wünschen übrig

      In der Dokumentation finde ich leider auch keine Alternative zu $mysqli->next_result(), also beispielsweise push_all_queries_at_once :-)
      Die einzelnen "Ergebnisse" interessieren mich nicht wirklich, da es sich nicht um SELECTs handelt und da auch nicht geprüft wird, ob die INSERTs erfolgreich waren...

      Sonst noch einen Tipp?

      Danke nochmal

      1. Tach!

        -phpmyadmin nutzt die PHP Erweiterung: mysql

        Die mysql-Extension hat keine Option für Multi-Querys. Der PMA kann damit also nur die Statements am Semikolon trennen und einzeln absetzen.

        -in meinem Script nutzte ich mysqli

        Ich weiß, das sieht man an den objektorientierten Aufrufen, die es nur in der mysqli-Extension gibt.

        Sonst noch einen Tipp?

        Zwei Dinge, die du probieren kannst:

        • Prepared Statements (hab ich schon erwähnt)
        • Statements einzeln mit mysqli::query() absetzen.

        dedlfix.

        1. Moin!

          Sonst noch einen Tipp?

          Zwei Dinge, die du probieren kannst:

          • Prepared Statements (hab ich schon erwähnt)
          • Statements einzeln mit mysqli::query() absetzen.

          Eine transaktionsfähige Table-Engine nutzen und den gesamten Query in einer Transaktion kapseln.

          - Sven Rautenberg

          1. Tach!

            Eine transaktionsfähige Table-Engine nutzen und den gesamten Query in einer Transaktion kapseln.

            Da ich Transaktionen noch nicht verwendet habe - lese ich da recht aus der Empfehlung, dass Transaktionen nur eine Ergebnismenge liefern und man nicht mit den next_result()-Aufrufen arbeiten muss? Diese verdächtige ich als den Zeitfresser (wobei mir grad einfällt, dass tester das mal mit Zeitmessungen prüfen sollte).

            dedlfix.

            1. Moin!

              Eine transaktionsfähige Table-Engine nutzen und den gesamten Query in einer Transaktion kapseln.

              Da ich Transaktionen noch nicht verwendet habe - lese ich da recht aus der Empfehlung, dass Transaktionen nur eine Ergebnismenge liefern und man nicht mit den next_result()-Aufrufen arbeiten muss? Diese verdächtige ich als den Zeitfresser (wobei mir grad einfällt, dass tester das mal mit Zeitmessungen prüfen sollte).

              Es ist performanter, explizit eine Transaktion zu eröffnen, dann gruppiert Veränderungen in die DB zu tun, und mit dem COMMIT diese dann insgesamt wirksam werden zu lassen, als implizit nach jedem Query ein automatisches COMMIT auszulösen.

              - Sven Rautenberg

              1. Tach!

                Es ist performanter, explizit eine Transaktion zu eröffnen, dann gruppiert Veränderungen in die DB zu tun, und mit dem COMMIT diese dann insgesamt wirksam werden zu lassen, als implizit nach jedem Query ein automatisches COMMIT auszulösen.

                Klingt zwar einleuchtend, aber wenn es der PMA mit mysql-Extension und in Einzelschritten schneller hinbekommt als mysqli im Paket - beides aber ohne Transaktion - bin ich vorläufig skeptisch, dass das was bringt. Transaktionen setzen zudem InnoDB als Storage Engine für die betreffende Tabelle voraus.

                dedlfix.