Shell oder MySQL
Kalle
- programmiertechnik
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
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
HI
OK und wenn wir von 50.000 ausgehen?
Kalle
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
Ich werd ums testen wohl nicht drum rum kommen :-)
Kalle
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
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
...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
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
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
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 ...
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
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
function checkid {
cat a.txt | while read id; do
if [ "$1" == "$id" ]; then
# Die angeforderte ID wurde gefunden
return 1
fi
done
}
cat b.txt | while read id; do
checkid $id
if [ $? -eq 0 ]; then
echo $id" not found"
else
echo $id" found"
fi
done
Kalle
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
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
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
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
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...
<?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
<?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
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
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
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