Mike: 200 Werte hintereinander in eine MYSQL Datenbank schreiben

Ich habe ein großes Formular, eine Tabelle. Da stehen ca. 200 INPUT Felder, also Variablen drin.

Nach dem Absenden, abspeichern, werden alle Variablen überprüft uns sollen dann in die Datenbank geschrieben werden.

foreach($einzelneVariablen AS $id_var => $wert) {	
$statement = $pdo->prepare("INSERT INTO ……..
}

Ich mache praktisch 200-mal die Datenbank auf, schreibe hinein, und schließe sie. Das ganze dauert gefühlt eine Ewigkeit. Kann man das beschleunigen, bzw. oder ganz anderes verwirklichen?

  1. Hallo,

    Kann man das beschleunigen, bzw. oder ganz anderes verwirklichen?

    Matthias hatte das Problem grade erst kürzlich.

    Gruß
    Kalk

  2. Hallo

    Ich habe ein großes Formular, eine Tabelle. Da stehen ca. 200 INPUT Felder, also Variablen drin.

    Nach dem Absenden, abspeichern, werden alle Variablen überprüft uns sollen dann in die Datenbank geschrieben werden.

    foreach($einzelneVariablen AS $id_var => $wert) {	
    $statement = $pdo->prepare("INSERT INTO ……..
    }
    

    Resultiert das in der Datenbank in einem Datensatz mit 200 Feldern oder erhält jeder Wert seinen eigenen Datenbankeintrag, so dass daraus 200 Zeilen in der Tabelle werden?

    Tschö, Auge

    --
    Ein echtes Alchimistenlabor musste voll mit Glasgefäßen sein, die so aussahen, als wären sie beim öffentlichen Schluckaufwettbewerb der Glasbläsergilde entstanden.
    Hohle Köpfe von Terry Pratchett
    1. Jeder Wert bekommt einen eigenen Datenbankeintrag, so dass daraus 200 Zeilen in der Tabelle werden!

      1. Tach!

        Jeder Wert bekommt einen eigenen Datenbankeintrag, so dass daraus 200 Zeilen in der Tabelle werden!

        Du brauchst das Prepare nur einmal abzuschicken (natürlich mit Platzhaltern bei den Werten), und kannst dann in der Schleife das Execute mit den jeweiligen Daten ausführen. (Bei PDO braucht man ja kein separates Binden, das macht das Execute.) Damit sparst du zumindest den Roundtrip für das Prepare. Wenn das immer noch zu lange dauert, hilft nur ein INSERT mit mehreren Datensätzen statt nur jeweils einem.

        INSERT ... VALUES (erster, Datensatz), (zweiter, Datensatz);

        dedlfix.

        1. Die Idde war nicht schlecht, aber

          mein Eintrag brauch 11,,5 Sek wenn ich nur einmal abschicke sind es 11,26 also fast kein Ersparniss.

          ich habe fast 200 Datensätze, du meinst ich soll die alle in eine INSERT Ausführung packen ?

          1. Hallo

            ich habe fast 200 Datensätze, du meinst ich soll die alle in eine INSERT Ausführung packen ?

            Klar, den Loop für die Vorbeireitung hast du natürlich immer noch mit 200 Durchläufen, aber den Datenbankrequest hast du dann nur noch einmal.

            Tschö, Auge

            --
            Ein echtes Alchimistenlabor musste voll mit Glasgefäßen sein, die so aussahen, als wären sie beim öffentlichen Schluckaufwettbewerb der Glasbläsergilde entstanden.
            Hohle Köpfe von Terry Pratchett
          2. Tach!

            ich habe fast 200 Datensätze, du meinst ich soll die alle in eine INSERT Ausführung packen ?

            Dann braucht es nur noch einen Roundtrip zum DBMS. Ich nehme an, das ist der Teil, der am meisten Laufzeit verbraucht.

            dedlfix.

          3. Die Idde war nicht schlecht, aber

            mein Eintrag brauch 11,,5 Sek

            Zeig mal dieses Inserstatement, das hätte ich gerne mal gesehen. Ist das mit oder ohne Verbindungsaufbau zu Mysql? MFG

            1. $statement = $pdo->prepare("INSERT INTO variablen ( formular, id_var, wert) VALUES (:formular, :id_var, :wert )");
              
              foreach($einzelneVariablen AS $variable => $wert) {
              
              $result = $statement->execute(array(
              'formular' => 1,
              'id_var' => $variable,
              'wert' => $wert ));
              	
              }
              
              1. Kann nicht sein daß son Insert mit 3 Feldern über 10 sek braucht. Da liegt das Problem woanders, evntl. an der Bandbreite. Wie lange braucht denn ein Verbindungsaufbau? Und inwieweit bist Du mit Wireshark (PCAP) vertraut? Damit kannst Du das mitschneiden und den Trace hier einstellen (wanst willst).

                MFG

                1. Tach!

                  Kann nicht sein daß son Insert mit 3 Feldern über 10 sek braucht.

                  Und wie verhält es sich bei den vorliegenden 200 Inserts?

                  dedlfix.

                  1. Hallo dedlfix,

                    50ms für einen SQL Request ist auch noch viel, finde ich.

                    Rolf

                    --
                    sumpsi - posui - clusi
                    1. Hallo Rolf,

                      50ms für einen SQL Request ist auch noch viel, finde ich.

                      Erst recht für einen einfachen INSERT.

                      LG,
                      CK

                      1. 50ms für einen SQL Request ist auch noch viel, finde ich.

                        Erst recht für einen einfachen INSERT.

                        Kommt, wie Multininsert - aka… ach lassen wir dass - schon sagt, auf die Gegebenheiten an. Bei hinreichend fetter Tabelle samt umfangreicher Indizes kann das schon sein. Schnell lesen oder schnell schreiben kann eine bewusste Entscheidung sein...

                        Ich kann in dem Thread keinen Hinweis auf die Gegebenheiten erkennen. Harter Test auf das Szenario wäre (sofern DB und Client auf demselben Server liegen): Die (Multiple-)Inserts als ein Statement direkt auf dem Server absetzen.

                        Rennt das oder performed es ebenfalls mies?

                        1. Hallo Mitleser,

                          Rennt das oder performed es ebenfalls mies?

                          Inserts mit mehreren Werten sind „nur“ syntaktischer Zucker über mehrere Inserts nacheinander. Man spart sich Roundtrips. Klar, das bringt etwas, aber vermutlich nicht viel. Wenn das tatsächlich nennenswert Performance bringt, würde das auf Netzwerk-Probleme hindeuten.

                          Für Bulk-Inserts haben die Datenbanken ansonsten auch Tips. Bei MySQL ist das stark abhängig von dem Tabellen-Treiber.

                          Für InnoDB gilt im wesentlichen: wrappe alles in eine Transaktion und schalte alle Checks für Unique und Foreign Keys aus – davon würde ich allerdings abraten, wenn man nicht gerade in einer Umgebung ist, bei der einem keiner in die Quere kommen kann…

                          Bei MyISAM ist es komplizierter.

                          Nichtsdestotrotz: wenn 200 Inserts so viel Zeit benötigen, dann läuft was schief. Ich würde mir da eher sowas wie Trigger oder so anschauen. Oder ist das eine Umgebung mit sehr vielen konkurrierenden Zugriffen? In dem Fall könnte es ein Locking-Problem sein… so oder so, außer „das sieht komisch aus“ kann man nicht viel sagen bei der Informationslage…

                          LG,
                          CK

                2. 10 Sekunden für 200 insert

                  1. 10 Sekunden für 200 insert

                    Macht 20 Insert pro Sekunde oder 50 Millisekunden pro Anfrage basteln, Anfrage stellen, Insert und Antwort empfangen. Wenn die Verbindung zwischen PHP und Datenbankserver via Netzwerk besteht ist das in einem Bereich, der (besonders wenn DSL oder VPN oder 2000km+10 Router dazwischen sind) einfach mal zu erwarten ist.

                    Pinge doch mal den Datenbankserver. Dann weisst Du es. Zur Abhilfe habe ich genug geschrieben.

                  2. 10 Sekunden für 200 insert

                    So!? Hat sich hier aber ganz anders gelesen. Nun, Kommunikation ist nicht jedermanns Sache. Webformulare die zu 200 Inserts führen, ganz sicher auch nicht.

                    MFG

                    1. Hallo Emil,

                      10 Sekunden für 200 insert

                      So!? Hat sich hier aber ganz anders gelesen.

                      Nö, das klang IMHO schon ziemlich genau so.

                      LG,
                      CK

              2. foreach($einzelneVariablen AS $variable => $wert) {
                
                $result = $statement->execute(array(
                'formular' => 1,
                'id_var' => $variable,
                'wert' => $wert ));
                	
                }
                

                Das macht 200x:

                "INSERT INTO TABLE `tabelle` (
                    `id`,
                    `formular`,
                    `wert`
                ) VALUES (
                     $i,
                     $variable,
                     $wert
                );
                

                Danach wird 200x der Index neu gebaut. Das dauert halt. Weder MySQL noch MariaDB sind für schnelles Indexieren bekannt und vielleicht ist auch noch ein lahmes Netz dazwischen. Du bist ja mit Informationen äußerst zurückhaltend und schwammig. Was ist denn unter IT-Leuten ist eine "gefühlte Ewigkeit"? (SAP-Anwender sollen angeblich sehr geduldig sein… Mich nervt jede Sekunde)

                Das ist wie wenn die Dame (der man an der Einganstür eben noch höflich die Tür aufhaltend den Vortritt gelassen hat) beim Fleischer immer GENAU EINE Scheibe ("Aber bitte recht dünn!") von der Salami ordert und, wenn die Wurst gewogen das Paket schon verpackt ist, insgesamt 200x mit "Ach wissen Sie, ich nehme doch noch eine." das ganze Wiegen, Berechnen und Packen von vorn beginnen lässt.

                Und alle hinter ihr sie eigentlich nur anschreien wollen.

                Deshalb sollst Du EINEN Multininsert bauen!

                "INSERT INTO TABLE `tabelle` (
                    `id`,
                    `formular`,
                    `wert`
                ) VALUES (
                     $i[0],
                     $variable[0],
                     $wert[0]
                ), (
                     $i[1],
                     $variable[1],
                     $wert[1]
                ), 
                ...
                (
                     $i[199],
                     $variable[199],
                     $wert[199]
                );
                
                

                Achte darauf, alle aus unsicheren Quellen stammende oder mutmaßlich womöglich merkwürdiges Zeug enthaltenen Werte zu "entgiften". Da Du nichts dazu aussagst empfehle ich bei Verwendung von PDO:

                • für Strings: $string = $conn->quote( $string );,
                • für Integer: $i = intval( $i );
                • für Float/Dezimalzahlen: $f = intval( $f );

                In Deinem Fall also etwa so:

                $sql='INSERT INTO `variablen` ( `formular`, `id_var`, `wert`) VALUES ';
                
                $ar = [];
                
                foreach( $einzelneVariablen AS $variable => $wert ) {
                    $ar[] = '(' 
                           . intval( $formular ) 
                           . ','
                           . $conn->quote( $variable )
                           . ','
                           . $conn->quote( $wert )
                           . ')'
                           . PHP_EOL; 
                           /* Der Zeilenumbruch für Fehlermeldungen/Debuggen */
                }
                
                if( count( $ar ) ) {
                    $sql .= implode( ',', $ar );
                    $count = $conn->exec( $sql );
                    /* Ausgaben? */
                } else {
                    /* Ausgaben? */
                }
                unset( $ar );
                
  3. Ich habe ein großes Formular, eine Tabelle. Da stehen ca. 200 INPUT Felder, also Variablen drin.

    Dein Lösungsansatz beginnt übrigens da bei den 200 Inputfeldern. MFG