2011-03-12 6 views
0

J'ai donc travaillé sur un jeu IRC depuis un an, écrit en PHP et utilisant un framework PHP vers IRC. Récemment, j'ai ajouté la possibilité d'archiver les scores (ils sont réinitialisés à chaque couple de centaines de jeux), ce qui m'a forcé à mettre à jour diverses fonctions d'administration.
Je viens de mettre à jour une fonction qui me permet de fusionner deux joueurs (certains utilisateurs ne cherchent pas leur ancien mot de passe etc ...) afin de fusionner aussi les partitions archivées (au cas où une réinitialisation aurait eu lieu avant que je trouve les comptes dupliqués).Optimisation des requêtes MySQL

La partie de score fusion (ci-dessous) fonctionne a l'intention, mais je me demande si je peux optimiser le processus parce que je trouve assez lourd (mais ne peut pas penser à quelque chose de mieux):

$from_stats = $this->db->query("SELECT `games`, `wins`, `points`, `date_archive` FROM ".$this->dbprefix."score WHERE `id`=".$id1." AND `channel`='".$gamechan."' GROUP BY `date_archive`"); // get scores for the original account 
$to_stats = $this->db->query("SELECT `games`, `wins`, `points`, `date_archive` FROM ".$this->dbprefix."score WHERE `id`=".$id2." AND `channel`='".$gamechan."' GROUP BY `date_archive`"); // get scores for the duplicated account 
$from_games = array(); 
$from_wins = array(); 
$from_points = array(); 
$from_date = array(); 
while (list($fromstats_games,$fromstats_wins,$fromstats_points,$fromstats_date) = $this->db->fetchRow($from_stats)) { // build score arrays for the original account 
    $from_games[count($from_games)] = $fromstats_games; 
    $from_wins[count($from_wins)] = $fromstats_wins; 
    $from_points[count($from_points)] = $fromstats_points; 
    $from_date[count($from_date)] = $fromstats_date; 
} 
$to_games = array(); 
$to_wins = array(); 
$to_points = array(); 
$to_date = array(); 
while (list($tostats_games,$tostats_wins,$tostats_points,$tostats_date) = $this->db->fetchRow($to_stats)) { // build score arrays for the duplicated account 
    $to_games[count($to_games)] = $tostats_games; 
    $to_wins[count($to_wins)] = $tostats_wins; 
    $to_points[count($to_points)] = $tostats_points; 
    $to_date[count($to_date)] = $tostats_date; 
} 
foreach ($from_date as $key1 => $id1_date) { 
    foreach ($to_date as $key2 => $id2_date) { 
     if ($id1_date == $id2_date) { // merge scores if dates match 
      $from_games[$key1] += $to_games[$key2]; 
      $from_wins[$key1] += $to_wins[$key2]; 
      $from_points[$key1] += $to_points[$key2]; 
      $this->db->query("UPDATE ".$this->dbprefix."score SET `games`=".$from_games[$key1].", `wins`=".$from_wins[$key1].", `points`=".$from_points[$key1]." WHERE `id`=".$id1." AND `channel`='".$gamechan."' AND `date_archive`='".$id1_date."'"); 
      break; 
     } 
    } 
} 
$this->db->query("DELETE FROM ".$this->dbprefix."score WHERE `id`=".$id2); // delete all entries for the duplicated account 

Répondre

0

Juste un conseil: après tout utiliser cette requête (si vous avez privilages appropriés)

$this->db->query("OPTIMIZE TABLE ".$this->dbprefix."score"); 

cela devrait faire tous les index dans ce tableau pour être recalculés. Vous remarquerez que la taille du fichier d'index a changé à 1kb (ou quelques octets)

+0

Merci, le fera :) – shroom

+0

encore une chose, au lieu de DELETE FROM envisager d'utiliser TRUNCATE TABLE - s'il n'y a pas de déclencheurs qui devraient être exécuté, c'est un moyen plus rapide que DELETE –

+0

Oui, je l'utilise sur d'autres cas, mais ici, je devais supprimer les entrées sélectionnées. Merci pour vos commentaires :) – shroom