tobi85: mysqli langsamer als mysql

Hallo,

weil wir zu PHP7 wechseln wollen, haben wir von mysql zu mysqli umgestellt. An den Abfragen etc. haben wir überhaupt nichts geändert, sondern lediglich die Funktion geändert.

Nun ist es so, dass nach der Umstellung unsere Seite bei mysqli viel viel langsamer ist. Kann das sein und an was könnte es liegen?

  1. gleicher Server? Gleiche Konfiguration? Und was meinst du mit "Seite", hast du die DB Queries nicht separat gemessen? Was für eine Art Benchmark hast du benutzt? Was sagt der Profiler?

  2. Nun ist es so, dass nach der Umstellung unsere Seite bei mysqli viel viel langsamer ist. Kann das sein

    Eher nicht.

    und an was könnte es liegen?

    Wenn es wirklich so ist, dass nur die neue, PHP7-gerechte Variante langsamer ist, dann sehr wahrscheinlich am Skript. Oder wurde auch die Datenbank neu eingerichtet?

    1. Hallo,

      also geändert habe ich "eigentlich" nur

      $res = mysql_query($q);

      zu

      $res = $mysqli->query($q);

      Es ist der selbe Server, die selbe Seite - alles identisch...

      1. "eigentlich"

        1. Auch uneigentlich...

          Normal sollte doch mysqli und PHP7 merklich schneller sein?

      2. Hallo und guten Morgen,

        also geändert habe ich "eigentlich" nur

        $res = mysql_query($q);

        zu

        $res = $mysqli->query($q);

        Da hast Du dann aber gleich zwei wesentliche Dinge geändert:

        • prozeduraler Stil --> objektorientiert
        • mysql standard --> mysqli (improved)

        Wo lässt Du denn deine Objekte erstellen? Werden die in einer Datenbankklasse erstellt und dann durchgereicht oder werden sie in jeder Funktion neu erstellt? Ich vermute mal, dass dort der Performanceverlust steckt.

        Grüße
        TS

        --
        es wachse der Freifunk
        http://freifunk-oberharz.de
        1. Dass er seine Connection nicht pro Query neu erstellen soll, haben wir ihm eigentlich klar genug gesagt. Also gehe ich davon aus, dass er das auch gemacht hat.

          NICHT WAHR, TOBI ??? ;-)

          1. Hallo, also ich lasse am Anfang vom Skript einmal eine Verbindung aufbauen. Über eine Globale Variable reiche ich diese Verbindung dann weiter - ist doch korrekt, oder?

            Es könnte aber auch an der PHP7 .ini liegen. Leider habe ich hierzu nichts passendes im Netz gefunden, wie man die php.ini am besten konfiguriert. Sollte ich diese mal so einstellen, wie meine "alte" PHP 5.6 ini Datei?

            1. Es mag aus Sicht von "Evil Global" Evangelisten vielleicht nicht korrekt sein, aber man kann es so machen und es sollte zumindest nicht zu einem Performanceverlust führen.

              Zur php.ini kann ich Dir auch nicht viel sagen.

              Kannst Du den Tempoverlust denn irgendwie eingrenzen? In einem PHP Projekt, an dem ich mit gebastelt hatte, waren alle SQL Abfragen mit einer Zeitmessung per microtime() eingerahmt, so dass man am Ende sagen konnte: Das Rendering dieser Seite benötigte 17ms, davon 9ms für SQL. Allerdings war da die Infrastruktur auch so, dass die Abfragen gekapselt waren und nur an 5 oder 6 Stellen gemessen werden musste. Falls Du bestimmte Abfragen im Verdacht hast (und den alten Sourcecode noch hast), könntest Du auf diese Weise ein Profiling versuchen - dafür musst Du die Zeitmessung natürlich im alten und im neuen Code einbauen.

              Betrachte dabei aber nicht nur den mysqli->query Aufruf, sondern den kompletten Vorgang von query bis "letzte Row eingelesen".

              Gruß Rolf

              1. Tach!

                Betrachte dabei aber nicht nur den mysqli->query Aufruf, sondern den kompletten Vorgang von query bis "letzte Row eingelesen".

                PHP arbeitet bei MySQL so, dass bei einem Query automatisch im Hintergrund die Ergebnismenge vom Datenbankserver abgefragt und zwischengespeichert wird. Für mysqli_query() kann man das über den Parameter $resultmode steuern. Lässt man den auf dem Defaultwert stehen, ist der Vorgang bereits mit dem mysqli_query() komplett. Und selbst wenn man ungepuffert auf die Daten zugreift, ist es nicht unbedingt sinnvoll, bis zum "letzte Row eingelesen" zu messen. Man kann ja beliebig viel Code je Row ausführen, nicht unbedingt nur ein einfaches Kopieren in ein Array, zum Beispiel.

                Beim Zwischenspeichern wird teilweise recht viel Speicher verwendet, weil Daten aus dem internen Puffer in Variablen kopiert werden müssen. Das Verhalten hat erst die Extension mysqlnd optimiert, so dass das über die PHP-übliche Quasi-Referenz ohne wirklich zu kopieren abgehandelt wird. Mit anderen Worten: schauen ob mysqlnd installiert ist (über phpinfo() beispielsweise). Es ändert sich an der Bedienung nichts, die geht weiterhin über mysqli. mysqlnd arbeitet unsichtbar im Hintergrund.

                "PHP-übliche Quasi-Referenz" nenne ich mal das Copy-on-Write-Prinzip, das PHP beim Variablen-Handling anwendet. Wenn man einen Wert in einer Variable einer anderen Variable zuweist, wird der nicht direkt dupliziert, sondern es wird zunächst lediglich ein Verweis auf den bisherigen Wert in den Metadaten der neuen Variable notiert. Erst wenn die Daten geändert werden, wird die tatsächliche Kopie erzeugt.

                dedlfix.