Kalle: Shell oder MySQL

Hi!

Ich hab da mal ne Frage...

Stellt euch eine Datei vor mit 5.000 IDs je 5 Zeichen lang
Jetzt stellt euch vor wie ich in einer forschleife jede ID einlese und prüfe
(sprich foreach(datei as id){ if ($id == $pruef) return 1; break(); } )
Ich hoffe ihr könnt euch unter diesem Pseudocode etwas vorstellen :)
Eine MySQL Datenbank wäre viel schneller oder?
(SELECT * FROM idcontainer WHERE id='".$pruef."')

Kalle

  1. Hi,

    ob das wirklich ein grosser Unterschied ist? Schliesslich sind die paar
    Einträge ja lächerlich klein um hier einen Unterschied zu suchen.

    Bin jetzt auch zu faul das zu testen, aber wenn das wirklich eine realistische Abfrage ist, würde ich Mysql höchstens benutzen weil die Daten da eh drin stehen, ansonsten hätte das was von mit Kanonen auf Spatzen schiessen.

    Mike

    1. HI

      OK und wenn wir von 50.000 ausgehen?

      Kalle

      1. Hi,

        OK und wenn wir von 50.000 ausgehen?

        befinden wir uns immer noch einer Region bei der ich Files oder sqlite
        bevorzugen würde, weil immer noch sehr wenig.

        Das hängt natürlich auch davon ab was genau drin steht und geprüft werden
        soll. Wenn wirklich kaum Schreibzugriffe da sind und das nur ein simpler Eintrag je Zeile ist denke ich erst an Mysql ab einer Dateigrösse von 500.000kb.  Oder natürlich wenn komplizierte Update-Prozeduren hinzukommen.

        Mike

        1. Ich werd ums testen wohl nicht drum rum kommen :-)

          Kalle

          1. Hi,

            Ich werd ums testen wohl nicht drum rum kommen :-)

            so siehts wohl aus ;-)

            Wenn ich mal raten darf, File wird in deinen Grössenordnungen schneller sein.

            Mike

            1. OK ich versuche es bis morgen mal getestet zu haben, damit das Archiv auch was davon hat. Vll kann man ja auch sowas wie einen Break-Even-Point feststellen, oder würde sich das von Prozessor zu Prozessor unterscheiden?

              Kalle

              1. ...Vll kann man ja auch sowas wie einen Break-Even-Point feststellen, oder würde sich das von Prozessor zu Prozessor unterscheiden?

                Das wäre mal interesannt zu wissen, und ja natürlich würde das von mehr als einem Faktor abhängen, insbesondere von der Server/Mysql Implementierung und der Konfiguration und vor allem auch von Zugriffen, usw...

                Also im Grunde genommen so, als willst du messen wie lange es dauert bis Wasser kocht.
                Temperatur, Druckverhältnis, Wärmeleitfähigkeit Behältnis, usw.....

                Man kann es nicht perfekt für alle Umgebungen herausfinden, aber dein "Break-Even-Point" bezogen auf eine einzige Umgebung, fände ich schon interessant zu wissen.

                Mike

                1. So.. komme grade von nem Termin..
                  Jetzt muss ich erst mal nen Apache und PHP Installieren..
                  Dann bischen was Coden und dann ist der (Arbeits-)Tag auch rum ;-)
                  Die (Test-)Scripte stelle ich dann natürlich Online damit auch andere Ihre Ergebnisse Posten können.

                  Bis Später!
                  Kalle

                  1. SO ich mach mich jetzt heim!
                    Morgen sollte ich mit testen anfangen können.

                    Habe jetzt LAMPP Installiert und eine Datenbank test mit 2 Tabellen aufgesetzt und 88.834 Datensätze in die Tabelle "a" und in die Datei ids.txt erzeugt. Je 6 Zeichen lang.
                    Morgen erledige ich den Rest.
                    Hätte nicht gedacht das mich das so lange aufhält...

                    Tschö
                    Kalle

                    1. Hey,

                      Also:
                      Ich habe 137,015 Datensätze in der MySQL-DB "a" und in der Datei "a.txt"
                      die Datei b.txt besteht aus IDs der Tabelle a (alle 10.000 Datensätze mal eine ID rauskopiert)
                      danach habe ich jede ID nochmal darunter kopiert und ein Zeichen entfernt, so dass die ID nicht gefunden werden kann.
                      Jeweils wird die Datei b.txt in eine Schleife geladen und ...

                      • file_script.bash: ruft jedes mal eine weitere Schleife auf und durchläuft die a.txt bis etwas gefunden wurde.
                      • mysql_script.php: Fragt die Datenbank via SELECT ab.

                      srv:/opt/lampp/htdocs/test# time /opt/lampp/htdocs/test/file_script.bash
                      vVxPjK found
                      vVxPj not found
                      AE8sh2 found
                      AE8sh not found
                      6MFi9h found
                      6MFi9 not found
                      yYe5HU found
                      yYe5H not found
                      eRzqxs found
                      eRzqx not found
                      io12WM found
                      io12W not found
                      gnBAlC found
                      gnBAl not found
                      bjYmHo found
                      bjYmH not found
                      pPcwQl found
                      pPcwQ not found
                      jHvLqV found
                      jHvLq not found

                      real    1m32.975s
                      user    1m22.105s
                      sys     0m10.873s
                      srv:/opt/lampp/htdocs/test# time /opt/lampp/htdocs/test/mysql_script.php

                      vVxPjK found!
                      vVxPj not found!
                      AE8sh2 found!
                      AE8sh not found!
                      6MFi9h found!
                      6MFi9 not found!
                      yYe5HU found!
                      yYe5H not found!
                      eRzqxs found!
                      eRzqx not found!
                      io12WM found!
                      io12W not found!
                      gnBAlC found!
                      gnBAl not found!
                      bjYmHo found!
                      bjYmH not found!
                      pPcwQl found!
                      pPcwQ not found!
                      jHvLqV found!
                      jHvLq not found!

                      real    0m1.385s
                      user    0m0.060s
                      sys     0m0.004s
                      srv:/opt/lampp/htdocs/test#

                      Das ist Enorm!
                      Deutlich geworden ist, dass die "Faulen" IDs im Bash-Test nahe zu doppelt so lange brauchen, bis ein Ergebnis ausgegeben wird, wie vorhandene IDs!
                      MySQL macht da keinen unterschied!

                      Ich werde jetzt wieder Datensätze rausnehmen bis ich auf den BEP komme ;-)

                      Wer das Script haben will meldet sich!

                      Kalle

                      1. So und nochmal mit 10.000 Sätzen

                        mysql_script.php
                        real    0m0.168s
                        user    0m0.044s
                        sys     0m0.024s

                        file_script.bash
                        real    0m5.982s
                        user    0m5.308s
                        sys     0m0.676s

                        aber ich glaube das man file_script.bash noch optimieren kann. Der Schleifen durchlauf ist nicht die perfekte vorgehensweise.

                        Hier mal der Code:

                        #! /bin/bash

                        Funktion zum durchlaufen der a.txt (Alle gespeicherten IDs)

                        function checkid {
                            cat a.txt | while read id; do
                                if [ "$1" == "$id" ]; then
                                    # Die angeforderte ID wurde gefunden
                                    return 1
                                fi
                            done
                        }

                        Schleife zum durchlaufen der b.txt (Zu prüfende IDs)

                        cat b.txt | while read id; do
                            checkid $id
                            if [ $? -eq 0 ]; then
                                echo $id" not found"
                            else
                                echo $id" found"
                            fi
                        done

                        Kalle

                        1. Hi,

                          wie/womit erhältst du die Zeitwerte?

                          if [ "$1" == "$id" ]; then

                          Nicht so wichtig, aber warum die Variabeln in ""?

                          Und warum eine Schleife?

                          $fl    = file('b.txt');
                          $check = array_search($id,$fl);
                          if(!$check){echo 'ID nicht vorhanden';}else{echo 'ID an Position: '.$check;}

                          *ungetestet

                          Mike

                          1. Mir fällt gerade ein, du willst ja nur wissen ob vorhanden oder nicht. In dem Fall gehts natürlich noch schneller:

                            $fl = file_get_contens('a.txt');
                            if(strripos($fl,$id) ){echo 'ID vorhanden';}else{'ID nicht vorhanden';}

                            Mike

                            1. Mir fällt gerade ein, du willst ja nur wissen ob vorhanden oder nicht.

                              Ja oder was kann man noch prüfen um heraus zu finden was schneller ist?!

                              #! /opt/lampp/bin/php

                              <?php
                              $fl = file_get_contents('a.txt');

                              foreach(file("b.txt") as $id){
                               $id = trim($id);

                              if(strripos($fl,$id)) { echo $id." vorhanden\n"; }else{ echo $id." nicht vorhanden\n"; }
                              }
                              ?>

                              srv:/opt/lampp/htdocs/test# time /opt/lampp/htdocs/test/file_script.php
                              real    0m0.088s
                              user    0m0.080s
                              sys     0m0.008s

                              srv:/opt/lampp/htdocs/test# time /opt/lampp/htdocs/test/mysql_script.php
                              real    0m0.171s
                              user    0m0.056s
                              sys     0m0.008s

                              Das sieht schon ganz anders aus...
                              Jetzt muss ich wieder Datensätze rein kloppen :)

                              Aber wichtig wäre mir noch vergleichbare Befehle für die Shell-Programierung zu finden.

                              Kalle

                              1. 100.000 Datensätze:

                                srv:/opt/lampp/htdocs/test# time /opt/lampp/htdocs/test/file_script.php
                                real    0m0.337s
                                user    0m0.312s
                                sys     0m0.024s

                                srv:/opt/lampp/htdocs/test# time /opt/lampp/htdocs/test/mysql_script.php
                                real    0m0.949s
                                user    0m0.060s
                                sys     0m0.008s

                                Das ist schon schnell oder :-)
                                18*100.000 Datensätze in nicht ein mal einer Sekunde und file_script.php ist fast drei mal so schnell. d.h. ich erhöhe auf 300.000 Datensätze - wobei das dieser test jetzt mehr vom Arbeitsspeicher abhängig ist als vom Festplattenzugriff. Was testen wir hier also?

                                Kalle

                                1. 224,266 Datensätze

                                  mysql_script.php
                                  real    0m2.003s
                                  user    0m0.064s
                                  sys     0m0.004s

                                  file_script.php
                                  real    0m0.747s
                                  user    0m0.712s
                                  sys     0m0.036s

                                  Ich hab keine Lust mehr...

                              2. <?php
                                $fl = file_get_contents('a.txt');

                                foreach(file("b.txt") as $id){
                                $id = trim($id);

                                if(strripos($fl,$id)) { echo $id." vorhanden\n"; }else{ echo $id." nicht vorhanden\n"; }
                                }
                                ?>

                                brrrrm wofür die Schleife? Die ist hier sinnlos und überflüssig.

                                <?php

                                // Das ist alles, keine Schleife

                                $fl = file_get_contents('a.txt');
                                if(strripos($fl,$id)) { echo $id.' vorhanden'; }
                                else{ echo $id.' nicht vorhanden'; }

                                ?>

                                Mike

                                1. <?php
                                  $fl = file_get_contents('a.txt');

                                  foreach(file("b.txt") as $id){
                                  $id = trim($id);

                                  if(strripos($fl,$id)) { echo $id." vorhanden\n"; }else{ echo $id." nicht vorhanden\n"; }
                                  }
                                  ?>

                                  Also Mike,
                                  Wofür die schleife?
                                  Ich suche ja nicht nur eine ID sondern 18 IDs in den jeweils 100.000 Datensätze

                                  also durchlaufe ich alle 18 IDs der Datei b.txt und suche diese in der a.txt (Oder DB-TBL a) worin sich alle IDs befinden. Deshalb eine Schleife.

                                  Kalle

                      2. Hallo Kalle,

                        Deutlich geworden ist, dass die "Faulen" IDs im Bash-Test nahe zu doppelt so lange brauchen, bis ein Ergebnis ausgegeben wird, wie vorhandene IDs!

                        Logisch, die Datei muss für nicht-vorhandene IDs ja immer komplett durchlaufen werden, für vorhandene dagegen im Mittel nur bis zur Hälfte.

                        Grüße

                        Daniel

    2. Hello,

      ob das wirklich ein grosser Unterschied ist? Schliesslich sind die paar
      Einträge ja lächerlich klein um hier einen Unterschied zu suchen.

      ja, AAAABER:
      Dein File-basierter Ansatz führt eine lineare Suche aus. Wenn du davon ausgehst, dass du jede ID genau ein Mal suchst, hast du im Mittel (Anzahl ID/2) Vergleiche. Wenn du MySQL verwendest und einen Index auf die ID setzt, dann kommen Optimierungsvorgänge zum Einsatz, beispielsweise Binärsuche, wodurch die Vergleiche schon auf log(Anzahl ID) runter geht - andere Verfahren können noch weiter drücken.
      Anders herum ist es sicherlich schneller eine Datei zu öffnen als eine Verbindung zu MySQL herzustellen und Daten über die Verbindung abzurufen.

      Ansonsten bin ich aber dabei: der Praxisvergleich würde mich auch interessieren...

      MfG
      Rouven

      --
      -------------------
      sh:| fo:} ch:? rl:( br:& n4:{ ie:| mo:} va:) js:| de:] zu:| fl:( ss:) ls:& (SelfCode)
      Ist Dir langweilig? Willst du Spaß? Willst Du Party? Ganz einfach!!! Schicke eine SMS mit dem Bestellwort "Feuer" an die 112 und innerhalb von 5 Minuten stehen 20 Männer mit lustigen Partyhüten, Sirenen und Partywagen vor deinem Haus!  --  Herkunft unbekannt
  2. Hallo Kalle,

    Ist dieses Problem ein Grund, dass eine Anwendung langsam ist?
    Wenn ja, solltest Du erst noch genauer überlegen, warum das passiert.
    Ist ein einzelner Suchvorgang zu langsam oder führst Du einfach sehr viele Zugriffe durch, was dann in der Summe zu langsam ist.
    In letzterem Fall würde ich einfach die ganze Liste einmal einlesen und in einer Hashtabelle ablegen. So lang der Speicher reicht (was bei einigen Tausend einträgen kein Problem ist), wirst Du kaum etwas schnelleres finden.
    Wenn das Problem durch wenige oder einen einzelnen Zugriff entsteht, musst Du sehr viele Einträge haben. Dann ist komplettes Einlesen natürlich keine Option. Hier würde sich eine Datenbank als erster Schritt anbieten, diese organisiert die Daten schon auf der Platte so, dass sie sie nicht komplett lesen muss, um einen Eintrag zu finden.
    Alternativ kann man für so einen einfachen Fall auch selber ein entsprechendes Verfahren implementieren.
    Deine Daten sind sehr einfach strukturiert (nur kurze, gleichlange Einträge). Da sollte es sehr einfach sein, die Datei als Hash-Tabelle aufzubauen. Dann kannst Du die Position einer gesuchten ID direkt berechnen, an die Stelle in der Datei springen und dort nur einen bzw. einige wenige Werte einlesen. Es gibt aber vermutlich keinen Grund, das selbst zu machen, außer Interesse ;-)

    Grüße

    Daniel