[PHP] PHP/MYSQL - Award Vergabe nach Tagen - kompliziert - funktioniert nicht.

Dieses Thema im Forum "Webentwicklung" wurde erstellt von saNz, 17. November 2010 .

  1. 17. November 2010
    PHP/MYSQL - Award Vergabe nach Tagen - kompliziert - funktioniert nicht.

    Liebe Leute

    ich knobel die ganze Zeit daran, was ich falsch mache.

    mit 2 Usern funktioniert es, aber mit den orginalen 20.000 Mitgliedern, hört das Script einfach irgendwann auf ohne etwas auszugeben und vorallem ohne etwas in die Datenbanktabellen "Tagaward" zu schreiben, bei 2 Usern, schreibt er auch was in die Tabelle "Tagaward".

    Kurzes zum Code, was er machen soll...

    Er Soll alle User aus der Tabelle "User" nehmen, in der Tabelle "Hits" jeden Monatstag prüfen, wieviele Hits der User gemacht hat, und dann in die Tabelle "Tagaward" schreiben, wieviele bzw welchen Award er bekommt.

    Wie gesagt, bei 2'n gehts, bei 20.000 nicht.

    Vielleicht hat jemand ne Idee.

    Liebe Grüße: Code:

    PHP:
    <? php
    error_reporting
    "E_ALL"  );

    include 
    'functions.php' ;
    include 
    'config.php' ;



    $user = mysql_query ( "SELECT * from user ORDER by id" );
    $dump = 0 ;
    $dumpn = 0 ;
    while(
    $row = mysql_fetch_array ( $user )) {  // User durchlaufen
        
    $a = 0 //Tagesangabe auf 0
        
    while ( $a <= 31 ) {  // 31 Tage durchlaufen
        
    $a ++;  //Tag 1 usw..
        
    $tam = mysql_query ( "SELECT * from hits WHERE userid =' $row [ alias ] ' AND time =' $a '" );
        
    $dump = mysql_num_rows ( $tam );  // Anzahl der generierten Hits an dem Tag
        
    if ( $dumpn < $dump ) {  $dumpn = $dump ; }  // wenn 31 Tage durch, sortieren nach dem besten Tag
        
    }
        if (
    $dumpn >= 1000 ) {  mysql_query ( "INSERT INTO tagaward VALUES ('',' $row [ alias ] ','1000','1')" ); }
        elseif (
    $dumpn >= 750 ) {  mysql_query ( "INSERT INTO tagaward VALUES ('',' $row [ alias ] ','750','1')" ); }
        elseif (
    $dumpn >= 500 ) {  mysql_query ( "INSERT INTO tagaward VALUES ('',' $row [ alias ] ','500','1')" ); }
        elseif (
    $dumpn >= 250 ) {  mysql_query ( "INSERT INTO tagaward VALUES ('',' $row [ alias ] ','250','1')" ); }
        elseif (
    $dumpn >= 100  ) {  mysql_query ( "INSERT INTO tagaward VALUES ('',' $row [ alias ] ','100','1')" ); }
        elseif (
    $dumpn >= 50  ) {  mysql_query ( "INSERT INTO tagaward VALUES ('',' $row [ alias ] ','50','1')" ); }

    // und ja, eintragen des jeweiligen Awards    
        
        
        
    }

        

    ?>
    Also in erster Linie würde ich mich freuen wenn wir es zum laufen kriegen, gerne bin ich auch für Kritik offen und für Optimierungstipps, aber wenn es läuft, dann feier ich echt!

    Liebe Grüße,
    saNz
     
  2. 17. November 2010
    AW: PHP/MYSQL - Award Vergabe nach Tagen - kompliziert - funktioniert nicht.

    Puh das ist aber auch iwie ne harte Abfrage. Du holst 20.000 User raus. Das heißt die erste while-Schleife läuft schonmal 20.000 mal druch. Und in dieser Schleife durchläuft jeder User nocheinmal 31 Abfragen.

    Das sind ja 620,000 Abfragen.

    Kann mir vorstellen, dass die Abfragen je nach Server relativ lange dauern.
    Check mal in deiner php.ini den php_value max_execution_time Wert ob die nicht verursacht, dass das Script abgebrochen wird, weil es zu lange ausgeführt wird. Manchmal ist der ziemlich niedrig eingestellt.


    Hast du das ganze auch mal mit nur z.b. 5000 Usern probiert?

    PHP:
    $user = mysql_query ( "SELECT * from user ORDER by id LIMIT 0,5000" ); 
     
  3. 17. November 2010
    AW: PHP/MYSQL - Award Vergabe nach Tagen - kompliziert - funktioniert nicht.

    deine aufgabe liese sich mit ganzen 3 querys lösen

    PHP:
    <? php

    $query 
    mysql_query ( '
        SELECT u.`alias`
        FROM `users` u
        ORDER BY u.`id`'
    );
        
    $users  = array();    
    while(
    $user  mysql_fetch_assoc ( $query ))
        
    $users [] =  $user ;

    mysql_free_result ( $query );

    $query  mysql_query ( '
        SELECT h.`time`, h.`userid`
        FROM `hits` h
        ORDER BY h.`time`'
    );
        
    $hits  = array();
    while(
    $hit  mysql_fetch_assoc ( $query ))
        
    $hits [] =  $hit ;
        
    mysql_free_result ( $query );

    $values  = array();
    foreach(
    $users  as & $user ) {
        for(
    $day  1 $day  <=  31 ; ++ $day ) {
            
    $hitsday  0 ;
            
    $points   0 ;
            
            foreach(
    $hits  as & $hit ) {
                if(
    $hit [ 'time' ] ==  $day  &&  $hit [ 'userid' ] ==  $user [ 'alias' ]) {
                    ++
    $hitsday ;
                    unset(
    $hit );
                }
            }
            
            switch(
    true ) {
                default:
                    continue 
    2 ;
                    
                case (
    $hitsday  >=  1000 ):
                    
    $points  1000 ;
                    break;
                    
                case (
    $hitsday  >=  750 ):
                    
    $points  750 ;
                    break;
                    
                case (
    $hitsday  >=  500 ):
                    
    $points  500 ;
                    break;
                    
                case (
    $hitsday  >=  250 ):
                    
    $points  250 ;
                    break;
                    
                case (
    $hitsday  >=  100 ):
                    
    $hitsday  100 ;
                    break;
                    
                case (
    $hitsday  >=  50 ):
                    
    $hitsday  50 ;
                    break;
            }
            
            
    $values [] =  sprintf ( '"%s", %d, 1' $user [ 'alias' ],  $points );
        }
        
        unset(
    $user );
    }

    if(!empty(
    $values )) {
        
    $values  implode ( '), (' $values );
        
    mysql_query ( '
            INSERT INTO `tagaward`
            VALUES (' 
    $values  ');' );
    }

    unset(
    $hits $users $values );
    das sollte schneller laufen und weniger performance beanspruchen. denn lieber lässt du ne schleife ein paar mal 20000x durchlaufen als mal eben 20000 querys abzusetzen. du wirst den unterschied merken.
     
  4. 18. November 2010
    AW: PHP/MYSQL - Award Vergabe nach Tagen - kompliziert - funktioniert nicht.

    Super mega liebe dank euch beiden.
    Ich bin es gar nicht mehr gewohnt das einem geholfen wird.

    Ich war bei php.de, und bekam dort als Antwort:
    (... von einem MODERATOR wohl gemerkt)


    Danke Jungs von RR

    Liebe Grüße,
    saNz
     
  5. 19. November 2010
    AW: PHP/MYSQL - Award Vergabe nach Tagen - kompliziert - funktioniert nicht.

    Bei php.de brauchste dich auch nicht zu wundern!

    Alles arrogante Snobs ^^

    Wenn da eine Anfrage stellst haste keine Lust mehr zu coden, war zumindest bei meinem ersten Versuch so ^^
     
  6. 19. November 2010
    AW: PHP/MYSQL - Award Vergabe nach Tagen - kompliziert - funktioniert nicht.

    Hey Murdoc,

    bin leider jetzt erst zum testen gekommen.
    Leider kommt bei deinem Script ein Fehler.
    Habe den Speicher schon auf 1024M gesetzt.
    Hast du vllt noch eine Idee woran es liegen könnte?

    Code:
    Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in C:\xampp\xampplite\htdocs\*****\awardtag.php on line 10
    
    Warning: mysql_free_result() expects parameter 1 to be resource, boolean given in C:\xampp\xampplite\htdocs\*****\awardtag.php on line 13
    
    Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 42 bytes) in C:\xampp\xampplite\htdocs\*****\awardtag.php on line 21
    
    Lg, saNz
     
  7. 19. November 2010
    AW: PHP/MYSQL - Award Vergabe nach Tagen - kompliziert - funktioniert nicht.

    query kontrollieren

    nö hast du nicht, weil laut der meldung 128M überschritten wurden.

    wenns nicht geht kann ich dir auch ne ne multi-prozess version basteln, dann sollte es keine speicherprobleme mehr geben. vielleicht wäres es in deinem fall allg. sinnvoller mit nem offset zu arbeiten und die daten schrittweise zu verarbeiten (also immer wieder nen teil). das könntest du dann mit einem crontab steuern.


    ps: hab mich mal auf php.de umgesehen -> was sind das denn für idioten?
     
  8. 19. November 2010
    AW: PHP/MYSQL - Award Vergabe nach Tagen - kompliziert - funktioniert nicht.

    Hab nun die Query gefixxt, es läuft schon seit 15Minuten, aber noch nichts in the tagaward tabelle.

    Steig leider auch nicht durch den Teil durch, wo du auswertest und in die tagaward tabelle schreibst, funktioniert das so wie du das geschrieben hast bei dieser Struktur?

    CREATE TABLE IF NOT EXISTS `tagaward` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `user` text NOT NULL,
    `award` text NOT NULL,
    `round` text NOT NULL,
    PRIMARY KEY (`id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

    --
    -- Daten für Tabelle `tagaward`
    --


    SOrry & Danke.

    Liebe Grüße,
    saNz
     
  9. 19. November 2010
    AW: PHP/MYSQL - Award Vergabe nach Tagen - kompliziert - funktioniert nicht.

    debug doch mal ein wenig mit
    PHP:
    print  'ich bin noch am leben' flush ();
    ansonsten hab ich noch nen fehler gefunden:
    PHP:
                 case ( $hitsday  >=  100 ):
                    
    $hitsday  100 ;
                    break;
                    
                case (
    $hitsday  >=  50 ):
                    
    $hitsday  50 ;
                    break;
    $hitsday = 100; und $hitsday = 50; in $points ändern.
     
  10. 19. November 2010
    AW: PHP/MYSQL - Award Vergabe nach Tagen - kompliziert - funktioniert nicht.

    Das ganze sollte eigentlich mit einem Query relativ performant funktionieren.

    Tabellenstruktur:
    Code:
    CREATE TABLE `dayaward` (
     `dayawardid` int(10) unsigned NOT NULL AUTO_INCREMENT,
     `userid` int(10) unsigned NOT NULL,
     `day` char(8) NOT NULL,
     `award` smallint(6) NOT NULL,
     PRIMARY KEY (`dayawardid`),
     KEY `userid` (`userid`,`day`)
    )
    
    CREATE TABLE `hit` (
     `hitid` int(10) unsigned NOT NULL AUTO_INCREMENT,
     `userid` int(10) unsigned NOT NULL,
     `time` int(10) unsigned NOT NULL,
     PRIMARY KEY (`hitid`),
     KEY `userid` (`userid`)
    )
    
    CREATE TABLE `user` (
     `userid` int(10) unsigned NOT NULL AUTO_INCREMENT,
     `name` varchar(35) NOT NULL,
     PRIMARY KEY (`userid`)
    )
    PHP:
    <? php
    $query 
    '
        INSERT INTO dayaward
        (
            userid,
            day,
            award
        )
        SELECT
            userid,
            "'
    . date ( 'Ymd' ). '",
            CASE
                WHEN COUNT(*)>=1000 THEN 1000
                WHEN COUNT(*)>= 750 THEN  750
                WHEN COUNT(*)>= 500 THEN  500
                WHEN COUNT(*)>= 250 THEN  250
                WHEN COUNT(*)>= 100 THEN  100
                WHEN COUNT(*)>=  50 THEN   50
            END AS award
        FROM user
        LEFT JOIN hit USING(userid)
        GROUP BY userid
        HAVING COUNT(*)>=50
    '
    ;
    ?>
    Ungetestet & nur als Besipiel!
     
  11. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.