php-resource



Zurück   PHP-Scripte PHP-Tutorials PHP-Jobs und vieles mehr > Entwicklung > SQL / Datenbanken
 

Login

 
eingeloggt bleiben
star Jetzt registrieren   star Passwort vergessen
 

 

 


SQL / Datenbanken Probleme mit SQL? Hier könnt ihr eure Fragen zu SQL (MySQL, PostgreSQL, MS-SQL und andere ANSI-SQL Server) los werden.

Antwort
 
LinkBack Themen-Optionen Thema bewerten
  #16 (permalink)  
Alt 22-08-2009, 12:21
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

Mach dir mal ne Tabelle mit sovielen Testeinträgen, wie du maximal im Laufe der Zeit erwartest und ruf die mit PHP ab, ob das performancemäßig wirklich so schlimm ist. Vielleicht kommst du da eher zum Ziel.
Mit Zitat antworten
  #17 (permalink)  
Alt 22-08-2009, 12:33
Benutzerbild von onemorenerd onemorenerd
  Moderator
Links : Onlinestatus : onemorenerd ist offline
Registriert seit: Mar 2005
Ort: Berlin
Beiträge: 9.471
onemorenerd wird schon bald berühmt werdenonemorenerd wird schon bald berühmt werden
Standard

Ich hoffe das Problem richtig verstanden zu haben ...
PHP-Code:
mysql_query('LOCK TABLES testsum READ');
$res mysql_query('SELECT SUM(wk1) FROM testsum');
$total mysql_result($res0);
$res mysql_query('SELECT * FROM testsum ORDER BY RAND()*(wk1/'$total .') DESC LIMIT 1');
$row mysql_fetch_object($res);
mysql_query('UNLOCK TABLES'); 
Zum Testen:
PHP-Code:
mysql_query('LOCK TABLES testsum READ');

$res mysql_query('SELECT SUM(wk1) FROM testsum');
$total mysql_result($res0);

$count = array();
for (
$i 0$i 1000$i++) {
    
$res mysql_query('SELECT id FROM testsum ORDER BY RAND()*(wk1/'$total .') DESC LIMIT 1');
    
$row mysql_fetch_object($res);
    isset(
$count[$row->id]) ? $count[$row->id]++ : $count[$row->id] = 1;
}
arsort($count);
echo 
'<pre>'.print_r($count,1).'</pre>';

mysql_query('UNLOCK TABLES'); 

Geändert von onemorenerd (22-08-2009 um 12:36 Uhr)
Mit Zitat antworten
  #18 (permalink)  
Alt 22-08-2009, 12:51
Boron
 Registrierter Benutzer
Links : Onlinestatus : Boron ist offline
Registriert seit: Aug 2004
Beiträge: 191
Boron ist zur Zeit noch ein unbeschriebenes Blatt
Standard

Die Lösung passt offensichtlich nicht ganz, denn die ID 3 wird selbst bei 10000 Schleifendurchläufen nicht getroffen!? Die Wahrscheinlichkeiten passen also nicht.
Mit Zitat antworten
  #19 (permalink)  
Alt 22-08-2009, 13:28
Benutzerbild von onemorenerd onemorenerd
  Moderator
Links : Onlinestatus : onemorenerd ist offline
Registriert seit: Mar 2005
Ort: Berlin
Beiträge: 9.471
onemorenerd wird schon bald berühmt werdenonemorenerd wird schon bald berühmt werden
Standard

Naja die ID 3 hat halt wk1=3, was angesichts der anderen wk1-Werte zu einer sehr niedrigen Wahrscheinlichkeit führt. Dann gibt es bei der Division Rundungsfehler und RAND() ist auch nicht perfekt (Computer können Zufall nicht perfekt nachbilden). Ich denke das führt eben dazu, dass ID 3 bei 1000 Versuchen nicht auftritt.
Hast du mal 100.000 oder noch mehr Versuche gemacht? Sollte selbst dann niemals ID 3 gezogen werden, müsste man sich mal RAND() im Zusammenspiel mit der Division genauer ansehen. Möglicherweise gibt es bei deinen Werten und der Ungenauigkeit von FLOAT überhaupt keine Chance für ID 3.

Nachtrag: SELECT 3/252; liefert 0.0119. Da ist schon ein gehöriger Rundungsfehler drin, denn eigentlich ist es 1,190476190476e-02 oder noch mehr.
Nachtrag2: Ich habe gerade 1.000.000 Versuche gemacht und auch dabei trat ID 3 nicht auf. Könnte zwar beim nächsten Anlauf anders sein, aber es erhärtet den Verdacht, dass so kleine Wahrscheinlichkeiten bei dieser Methode mit 0 zusammenfallen und diese Ereignisse dadurch niemals eintreten. Das ist dann aber kein Fehler sondern systembedingte Ungenauigkeit. Wenn das für dich nicht akzeptabel ist, musst du dir was anderes einfallen lassen. Entweder für andere wk1-Werte sorgen oder die Berechnung in einem Umfeld mit höherer Genauigkeit durchführen. Ein solches Umfeld wäre z.B. PHP mit bcmath.

Geändert von onemorenerd (22-08-2009 um 13:46 Uhr)
Mit Zitat antworten
  #20 (permalink)  
Alt 22-08-2009, 13:46
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

Zitat:
Zitat von onemorenerd Beitrag anzeigen
Nachtrag: SELECT 3/252; liefert 0.0119. Da ist schon ein gehöriger Rundungsfehler drin, denn eigentlich ist es 1,190476190476e-02 oder noch mehr.
Das ist kein Rundungsfehler. MySQL rechnet mit der Präzision der Argumente korrekt weiter. 3.0000/252.0000 liefert 0.01190476.

@Boron: Du kannst in der Abfrage natürlich auch eine PHP-generierte Zufallszahl verwenden. Mit mt_rand() sollte dann schon was vernünftigeres rauskommen. Außerdem kennst du die Zufallszahl dann und kannst wirklich überprüfen, ob der korrekte Eintrag ausgewählt wurde. Außerdem kannst du die Grenzbereiche zwischen den summierten Gewichten (29.999--30.001, 79.999--80.001, u.s.w.) gezielt abtesten.

Geändert von AmicaNoctis (22-08-2009 um 13:56 Uhr)
Mit Zitat antworten
  #21 (permalink)  
Alt 22-08-2009, 14:31
Boron
 Registrierter Benutzer
Links : Onlinestatus : Boron ist offline
Registriert seit: Aug 2004
Beiträge: 191
Boron ist zur Zeit noch ein unbeschriebenes Blatt
Standard

Ok, und wenn ich dafür willkürlich einen Mindestwert vorgebe, sodass die Zeile überhaupt irgendwann mal getroffen wird?

Sehe ich das richtig, dass das ORDER BY RAND()*(wk1/'. $total .') quasi für jeden Eintrag in der Tabelle vorgenommen wird? Das wäre bei vielen Datensätzen dann nicht mehr so prickelnd.

Beim anderen Ansatz wird über alle Einträge aufsummiert und nur einmal eine Multiplikation mit einer Zufallszahl vorgenommen... den fand ich intuitiv besser.

Zitat:
Du kannst in der Abfrage natürlich auch eine PHP-generierte Zufallszahl verwenden. Mit mt_rand() sollte dann schon was vernünftigeres rauskommen. Außerdem kennst du die Zufallszahl dann und kannst wirklich überprüfen, ob der korrekte Eintrag ausgewählt wurde.
Danke, das ist es!

PHP-Code:
$durchlaeufe 3000;
$result = array();
mysql_query('LOCK TABLES testsum READ');
$res mysql_query('SELECT SUM(wk1) FROM testsum');
$total mysql_result($res0);
for(
$i=0$i<$durchlaeufe$i++) {
    
$zufallszahl mt_rand(0$total);
    
mysql_query("SET @a := 0");
    
$qry mysql_query("SELECT  `name` , ((@a := @a +  `wk1`) -  `wk1` ) AS  `summe` 
                        FROM  `testsum`
                        HAVING `summe` <= "
.$zufallszahl."
                        ORDER BY `summe` DESC
                        LIMIT 1"
) OR DIE (mysql_error());
    
$row mysql_fetch_assoc($qry);    
    isset(
$result[$row['name']]) ? $result[$row['name']]++ : $result[$row['name']] = 1;
}
mysql_query('UNLOCK TABLES'); 
Das liefert mir doch sinnvolle Ergebnisse:
Code:
Array
(
    [Heidi] => 788 (0.263%)
    [Paul] => 569 (0.19%)
    [Klaus] => 871 (0.29%)
    [Caro] => 410 (0.137%)
    [Peter] => 327 (0.109%)
    [Simone] => 35 (0.012%)
)
So, hoffentlich hat sich nicht doch noch irgendwo ein Fehler eingeschlichen.
Mit Zitat antworten
  #22 (permalink)  
Alt 22-08-2009, 17:04
Benutzerbild von onemorenerd onemorenerd
  Moderator
Links : Onlinestatus : onemorenerd ist offline
Registriert seit: Mar 2005
Ort: Berlin
Beiträge: 9.471
onemorenerd wird schon bald berühmt werdenonemorenerd wird schon bald berühmt werden
Standard

Zitat:
Zitat von Boron Beitrag anzeigen
Sehe ich das richtig, dass das ORDER BY RAND()*(wk1/'. $total .') quasi für jeden Eintrag in der Tabelle vorgenommen wird? Das wäre bei vielen Datensätzen dann nicht mehr so prickelnd.

Beim anderen Ansatz wird über alle Einträge aufsummiert und nur einmal eine Multiplikation mit einer Zufallszahl vorgenommen... den fand ich intuitiv besser.
Der eine Ansatz berechnet wk1/$total, der andere Ansatz berechnet @a - beide rechnen so oft wie es Datensätze gibt.
Mit Zitat antworten
  #23 (permalink)  
Alt 22-08-2009, 17:09
Boron
 Registrierter Benutzer
Links : Onlinestatus : Boron ist offline
Registriert seit: Aug 2004
Beiträge: 191
Boron ist zur Zeit noch ein unbeschriebenes Blatt
Standard

Ok, aber die Summenbildung verursacht wahrscheinlich weniger Aufwand als die RAND()-Funktion und die Multiplikation, oder?

Hätte die Tabelle 100 Datensätze, würde im Verfahren A) 100 Mal aufsummiert und einmal RAND() angewendet werden.
Im Verfahren B) würde 100 Mal RAND() angewendet werden. Richtig?
Mit Zitat antworten
  #24 (permalink)  
Alt 22-08-2009, 17:17
Benutzerbild von onemorenerd onemorenerd
  Moderator
Links : Onlinestatus : onemorenerd ist offline
Registriert seit: Mar 2005
Ort: Berlin
Beiträge: 9.471
onemorenerd wird schon bald berühmt werdenonemorenerd wird schon bald berühmt werden
Standard

Das RAND() findet doch nun eh schon in PHP statt. Das ist auch richtig so. Jetzt bleibt bei genauer Betrachtung
A) 100 Additionen, 100 Subtraktionen, 100 Schreibzugriffe auf @a
B) 100 Divisionen

Keine Ahnung was schneller ist. Dürfte bei üblicher Tabellengröße auch kaum einen Unterschied ausmachen. Ich würde an deiner Stelle Variante B benutzen, weil sie einfacher zu verstehen ist. Du kanntest @-Variablen anfangs noch gar nicht, so geht es vielen ...
Mit Zitat antworten
Antwort

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
XML Elemente mit Attribut "minoccurs" versehen rolando80 XML 3 19-09-2007 16:44
Aus Variableninhalt "\t" wird "\\t" bei übergabe über URL / GET FrozenEmotions PHP Developer Forum 12 07-09-2007 18:11
XHTML 1.0 Transitional und "wrap" Attribut haSta HTML, JavaScript, AJAX, jQuery, CSS, Bootstrap, LESS 9 20-01-2006 18:28
Hilfeeeeee (bitte :-) Für Euch bestimmt ein "Klacks" Louisa27 PHP Developer Forum 8 27-04-2005 14:53
[HTML] Browserproblem mit dem Attribut wrap="virtual" Hendrik2 HTML, JavaScript, AJAX, jQuery, CSS, Bootstrap, LESS 2 15-06-2004 13:09

Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an


PHP News

ebiz-trader 7.5.0 mit PHP7 Unterstützung veröffentlicht
ebiz-trader 7.5.0 mit PHP7 Unterstützung veröffentlichtDie bekannte Marktplatzsoftware ebiz-trader ist in der Version 7.5.0 veröffentlicht worden.

28.05.2018 | Berni

Wissensbestand in Unternehmen
Wissensbestand in UnternehmenLebenslanges Lernen und Weiterbilden sichert Wissensbestand in Unternehmen

25.05.2018 | Berni


 

Aktuelle PHP Scripte

PHP Server Monitor

PHP Server Monitor ist ein Skript, das prüft, ob Ihre Websites und Server betriebsbereit sind.

11.09.2018 Berni | Kategorie: PHP/ Security
PHP WEB STATISTIK ansehen PHP WEB STATISTIK

Die PHP Web Statistik bietet Ihnen ein einfach zu konfigurierendes Script zur Aufzeichnung und grafischen und textuellen Auswertung der Besuchern Ihrer Webseite. Folgende zeitlichen Module sind verfügbar: Jahr, Monat, Tag, Wochentag, Stunde Folgende son

28.08.2018 phpwebstat | Kategorie: PHP/ Counter
Affilinator - Affilinet XML Produktlisten Skript

Die Affilinator Affilinet XML Edition ist ein vollautomatisches Skript zum einlesen und darstellen der Affili.net (Partnerprogramm Netzwerk) Produktlisten und Produktdaten. Im Grunde gibt der Webmaster seine Affilinet PartnerID ein und hat dann unmittelb

27.08.2018 freefrank@ | Kategorie: PHP/ Partnerprogramme
 Alle PHP Scripte anzeigen

Alle Zeitangaben in WEZ +2. Es ist jetzt 18:14 Uhr.