Archiv für den Monat: Januar 2011

sprintf und float-Zahlen in mySQL-Querys

Floats, also Fließkommazahlen, in eine DB zu schreiben sollte man können. Dachte ich bis vor kurzem 😉

Und deshalb, vor allem als Hinweis an mich selbst: Falls ein Query mit einem – vorher bereits vom Punkt befreiter, das Komma in Punkt umgewandelten – String plötzlich nicht mehr korrekt ausgeführt wird, dann liegt das höchstwahrscheinlich an zwei Sachen; allein, eine war mir dann neu:

  1. Du übergibst deinem Query die Parameter via sprintf (oder äquivalenten davon) und (jetzt kommt das neue)
  2. dein Server spricht plötzlich Deutsch!

Um einen fehlerhaften Query aber dauerhaft zu vermeiden, setze ich vor meinen Query nun die Sprache des Systems auf die Sprache der Datenbank und dannach wieder zurück. Den Quellcode habe ich stark vereinfacht mal hier angefügt.


// Wechsel zur internen Sprache der DB, als Beispiel fest im Code
$old = setlocale(LC_NUMERIC, NULL);
setlocale(LC_NUMERIC, 'us_US');

// Query ausführen. Werte im Query werden via sprintf eingegeben
// ...

// Zurück zur normalen Einstellung
setlocale(LC_NUMERIC, $old);

Ich hoffe, ich kann damit mal jemanden aus der Patsche helfen, wahrscheinlich bin ich aber wieder mal selbst mein bester Kunde 😉

String mit array-strings durchsuchen – Performance der Funktionen

Ich suche in einem String nach Teilstrings, die ich in einem Array habe. Die Funktion array_search macht leider genau das Gegenteil, deshalb brauche ich an dieser Stelle eine eigene Funktion.

Doch welche String-Suchfunktion verwende ich?
Zur Auswahl stehen folgende Funktionen, sollte ich was vergessen haben bitte ich um kurze Meldung:

Hier mal der Versuch einer Messung, wie schnell die Funktionen ihre Arbeit erledigen. Dazu lasse ich alle Funktionen nacheinander den String durchsuchen, das ganze mache ich je Funktion 9999 mal, um eine Tendenz sichtbar zu machen. Und ja: Quick and Dirty Code, ich bin mir dessen bewusst.


$arrHaystack = array( 'hallo',
'welt',
'foobar',
'php5',
'suchfunktion',
'bob',
'und',
'alice',
'suchen',
'strings',
'in',
'arrays',
'Lorem','ipsum','dolor','sit','amet','consetetur','sadipscing','elitr','sed','diam','nonumy','eirmod','tempor','invidunt','ut','labore','et','dolore','magna','aliquyam','erat','sed','diam','voluptua','At','vero','eos','et','accusam','et','justo','duo','dolores','et','ea','rebum','Stet','clita','kasd','gubergren','no','sea','takimata','sanctus','est','Lorem','ipsum','dolor','sit','amet','Lorem','ipsum','dolor','sit','amet','consetetur','sadipscing','elitr','sed','diam','nonumy','eirmod','tempor','invidunt','ut','labore','et','dolore','magna','aliquyam','erat','sed','diam','voluptua','At','vero','eos','et','accusam','et','justo','duo','dolores','et','ea','rebum','Stet','clita','kasd','gubergren','no','sea','takimata','sanctus','est','Lorem','ipsum','dolor','sit','amet','Lorem','ipsum','dolor','sit','amet','consetetur','sadipscing','elitr','sed','diam','nonumy','eirmod','tempor','invidunt','ut','labore','et','dolore','magna','aliquyam','erat','sed','diam','voluptua','At','vero','eos','et','accusam','et','justo','duo','dolores','et','ea','rebum','Stet','clita','kasd','gubergren','no','sea','takimata','sanctus','est','Lorem','ipsum','dolor','sit','amet','Duis','autem','vel','eum','iriure','dolor','in','hendrerit','in','vulputate','velit','esse','molestie','consequat','vel','illum','dolore','eu','feugiat','nulla','facilisis','at','vero','eros','et','accumsan','et','iusto','odio','dignissim','qui','blandit','praesent','luptatum','zzril','delenit','augue','duis','dolore','te','feugait','nulla','facilisi','Lorem','ipsum','dolor','sit','amet','consectetuer','adipiscing','elit','sed','diam','nonummy','nibh','euismod','tincidunt','ut','laoreet','dolore','magna','aliquam','erat','volutpat');

$iIterations = 100;
$suchsatz = array('meas magna','mia diam','im garten sind bob und alice','elixier des nichts');

$iMax = count($suchsatz);
$iStart = microtime(1);

for ($i=0;$i<$iIterations;$i++)
{
$iTake = mt_rand(0, $iMax);
foreach ($arrHaystack AS $key => $value)
{
if (mb_substr_count($suchsatz[$iTake], $value)>0)
{
break;
}
}
shuffle($arrHaystack);
}
$iEnd1 = microtime(1);

for ($i=0;$i<$iIterations;$i++)
{
$iTake = mt_rand(0, $iMax);
foreach ($arrHaystack AS $key => $value)
{
if (mb_stripos($suchsatz[$iTake], $value)!==FALSE)
{
break;
}
}
shuffle($arrHaystack);
}
$iEnd2 = microtime(1);

for ($i=0;$i<$iIterations;$i++)
{
$iTake = mt_rand(0, $iMax);
foreach ($arrHaystack AS $key => $value)
{
if (mb_stristr($suchsatz[$iTake], $value)!==FALSE)
{
break;
}
}
shuffle($arrHaystack);
}
$iEnd3 = microtime(1);

for ($i=0;$i<$iIterations;$i++)
{
$iTake = mt_rand(0, $iMax);
foreach ($arrHaystack AS $key => $value)
{
if (preg_match('/'.$value.'/i', $suchsatz[$iTake])>0)
{
break;
}
}
shuffle($arrHaystack);
}
$iEnd4 = microtime(1);

printf('--------------------------'."\n");
printf('mb_substr_count() -> %f'."\n",$iEnd1-$iStart);
printf('mb_stripos() -> %f'."\n",$iEnd2-$iEnd1);
printf('mb_stristr() -> %f'."\n",$iEnd3-$iEnd2);
printf('preg_match() -> %f'."\n",$iEnd4-$iEnd3);
printf('--------------------------'."\n");

Hier die Ergebnisse:
————————–
mb_substr_count() -> 15.756097
mb_stripos -> 16.490042
mb_stristr -> 16.938911
preg_match -> 14.681287
————————–

Schön zu sehen, dass meine intuitiv gewählte Funktion mb_substr_count() die Arbeit anscheinend am schnellsten erledigt. Überraschend für mich, dass der regex Platz 2 belegt und dass die anderen Funktionen einen so großen Abstand zu den beiden ersten Plätzen aufweisen.

Update 08.01.2011:
Habe den Code mal den Kommentaren angepasst. Das Array der Wörter ist nun 240 Felder groß, es wird nun auch zufällig einer von 4 Sätzen durchsucht. Nach jedem Treffer wird das Wort-Array zufällig neu ‚geschüttelt‘. Das sollte alle Caching-Sachen ausschalten.

Dabei bildet sich wirklich ein neues Bild (bei 100 durchläufen). Platz 1 geht nun an den regex, Platz 2 an substr_count, dicht gefolgt von den beiden stri-Funktionen. Insgesamt ist aber kein nennenswerter Abstand mehr vorhanden (im Gegensatz zum ersten Test), weshalb ich sagen kann: Nehmt, womit ihr am besten klarkommt. In High-Performance Umgebungen folgt dem Testergebnis.