Page 1 sur 3

Optimisation code

Posté : 09 nov. 2010, 08:43
par Gaara37
Bonjour à tous,

Je souhaiterais avoir votre avis afin d'optimiser le code source ci-dessous car les utilisateurs se plaignent de temps de réponse long lors du traitement du formulaire. Pour information, le serveur sur lequel est hébergé l'application n'est pas optimisé en ce qui concerne MySql, Php, Apache, mais ça ce n'est pas de mon ressort, c'est un autre service dans ma boîte qui doit s'en charger.
Voici un petit descriptif de l'application :

Sur un formulaire, j'ai un champ textarea (uniquement ce champ) qui contient un numéro pouvant aller de 17 à 19 caractères. D'après les utilisateurs, ils peuvent au maximum saisir jusqu'à 60 numéros. Au niveau des traitements, je dois traiter chaque numéro au cas par cas. Pour chaque numéro, je dois vérifier sa longueur et ajouter un ou deux zéros à telle position en fonction. Mais plutôt que tout décrire, voici le code. Mon souhait c'est optimiser pour que le traitement soit plus rapide si possible.
<?php
// Récupération des différents codebarre(numliaison)
$codebarre = explode("\n",trim($_POST['codebarre']));
$nb_codebarre = count($codebarre);

// On décompose la date du jour (date du jour est une variable défini dans un fichier de configuration)
$calc_purge_lots = explode("-",$date_jour);
$annee_purge = $calc_purge_lots[0];
$mois_purge  = $calc_purge_lots[1];
$jour_purge  = $calc_purge_lots[2];
			
// Calcul de la date de purge des lots non mis en carton
$date_purge_lots = date("Y-m-d", mktime(0, 0, 0, $mois_purge, $jour_purge+10, $annee_purge));
			
// On boucle sur tout les codes barre
for($i=0;$i<$nb_codebarre;$i++) {
  // On vérifie que le code barre n'est pas vide
  if ($codebarre[$i] != "") {
     // Colcul de la longueur de chaine de code barre et nettoyage des espaces en début et fin de chaine
     $longueur_codebarre = strlen(trim($codebarre[$i]));
     // Gestion du code barre sur la longueur en fonction du n° de lot sur 1 ou  2 ou 3 caractères, on ajoute les 0
     // De cette manière peu importe la longueur initiale, on récupére le quantième toujours au même position
     if ($longueur_codebarre == 17) {
	// On ajoute 2 zéro à num_lot
	$codebarre[$i] = substr_replace($codebarre[$i],"00",9,0);
     } else if ($longueur_codebarre == 18) {
    // On ajoute 1 zéro à num_lot
       $codebarre[$i] = substr_replace($codebarre[$i],"0",9,0);
    } else {
       $codebarre[$i] = $codebarre[$i];
    }
// Extrait du quantieme (jour dans l'année) à partir du code barre
$quantieme_codebarre = substr($codebarre[$i],12,3);

   // Colcul de la longueur de chaine de code barre suivant  et nettoyage des espaces en début et fin de chaine
   $longueur_codebarre_suivant = strlen(trim($codebarre[$i+1]));
   // Gestion du code barre sur la longueur en fonction du n° de lot sur 1 ou  2 ou 3 caractères, on ajoute les 0
  // De cette manière peu importe la longueur initiale, on récupére le quantième toujours au même position
  if ($longueur_codebarre_suivant == 17) {
	// On ajoute 2 zéro à num_lot
	$codebarre[$i+1] = substr_replace($codebarre[$i+1],"00",9,0);
  } else if ($longueur_codebarre_suivant == 18) {
	// On ajoute 1 zéro à num_lot
       $codebarre[$i+1] = substr_replace($codebarre[$i+1],"0",9,0);
  } else {
      $codebarre[$i+1] = $codebarre[$i+1];
  }
 // Extrait du quantieme (jour dans l'année) à partir du code barre suivant
 $quantieme_codebarre_suivant = substr(($codebarre[$i+1]),12,3);	
 // Extrait de l'année à partir du code barre
 $annee_codebarre = substr($codebarre[$i],15,4);
// Nettoyage des espaces
$codebarre_propre = preg_replace('/\s{1,}/','', $codebarre[$i]); 

// On vérifie que le lot est bien présent en base avant de faire un update (num_liaison est défini en index dans la table). Pour info, la table contient plus de 650 000 enregistrement format MyIsam.
$query_verif_lot = "select num_liaison from etj420 where (num_liaison  = '$codebarre_propre')";
$result_verif_lot = mysql_query($query_verif_lot) or die ('Erreur dans la requête : ' . $query_verif_lot . '<br>Avec l\'erreur : ' . mysql_error());
$nb_verif_lot = mysql_numrows($result_verif_lot);
// Le lot est bien présent
if ($nb_verif_lot > 0) {
	// On vérifie qu'on a pas déjà mis le lot en carton
	$query_verif_carton = "select num_liaison, code_site, num_carton from etj420 where (num_liaison  = '$codebarre_propre' and code_site = '$_SESSION[codesite]' and num_carton != '0')";
	$result_verif_carton = mysql_query($query_verif_carton) or die ('Erreur dans la requête : ' . $query_verif_carton . '<br>Avec l\'erreur : ' . mysql_error());
	$nb_verif_carton = mysql_numrows($result_verif_carton);
		if ($nb_verif_carton == 0) {
	   	   //On met à jour la table archive pour le n° de carton et le n° de travé en fonction du numliaison
		   $query_maj_archive = "update etj420 set num_carton = '$num_carton', code_site = '$_SESSION[codesite]' where num_liaison  = '$codebarre_propre'";
		   $result_maj_archive = mysql_query($query_maj_archive) or die ('Erreur dans la requête : ' . $query_maj_archive . '<br>Avec l\'erreur : ' . mysql_error());
		} else {
		   $lots_deja_encarton .= $codebarre_propre." ";
		}
}
// Le lot n'est pas présent, on stocke son n°
else {
// Nettoyage des espaces
   $lots_non_present .= $codebarre_propre." ";
}
  // On compare les 2 quantiemes, si ils sont différents, il faudra mettre à jour également la date de mise en carton et date d'épuration pour les 2 quantiemes
  if ($quantieme_codebarre != $quantieme_codebarre_suivant) {
  // On met à jour la table avec la date de mise en carton + la date d'épuration pour le quantieme du site
   $query_maj_carton = "update etj420 set date_mise_encarton='$date_jour', date_purge_lots='$date_purge_lots' where (quantieme ='$quantieme_codebarre' and annee='$annee_codebarre' and   code_site='$_SESSION[codesite]')";
 $result_maj_carton = mysql_query($query_maj_carton) or die ('Erreur dans la requête : ' . $query_maj_carton . '<br>Avec l\'erreur : ' . mysql_error());
  } else {
  // On met à jour la table avec la date de mise en carton + la date d'épuration pour le quantieme suivant du site
  $query_maj_carton = "update etj420 set date_mise_encarton='$date_jour', date_purge_lots='$date_purge_lots' where (quantieme ='$quantieme_codebarre_suivant' and annee='$annee_codebarre' and code_site='$_SESSION[codesite]')";
 $result_maj_carton = mysql_query($query_maj_carton) or die ('Erreur dans la requête : ' . $query_maj_carton . '<br>Avec l\'erreur : ' . mysql_error());
  }
 } // Fin du IF si le code barre n'est pas vide
} // Fin du FOR		
?>
En relisant mon code, c'est sûr il y a des choses à améliorer mais je bloque, comment améliorer le traitement pour qu'il soit plus rapide ?
Merci pour vos retours et désolé si mon code n'est pas des meilleurs mais je fais de mon mieux !

@+ tard

Re: Optimisation code

Posté : 09 nov. 2010, 12:37
par jojolapine
Bonjour,

Pour le fait d'ajouter 1 ou plusieurs 0 en fin de numéro, tu peux utiliser str_pad() (http://fr2.php.net/manual/fr/function.str-pad.php)
Qui fait tout tout seul ;)

J'ai ensuite fait deux trois améliorations minimes et surtout j'ai protégé toutes les entrées au sein de tes requêtes!

Tu pourrais aussi stocker directement un timestamp dans ton fichier de config pour $date_jour....

Sinon pour améliorer le tout, la solution est de faire des benchmarks, et de vérifier si des modifs améliorent le temps de traitement

Une dernière chose, à quoi sert ceci:
    $codebarre_propre = preg_replace ('/\s{1,}/', '', $codebarre[$i]);
Enlever les espace?
pourquoi ne pas mettre un bête str_replace?
$codebarre_propre = str_replace(' ','',$codebarre[$i]);
pour les autres modifs:
<?php
// Récupération des différents codebarre(numliaison)
$codebarre = explode (PHP_EOL, trim ($_POST['codebarre']));
$nb_codebarre = count ($codebarre);

// On décompose la date du jour (date du jour est une variable défini dans un fichier de configuration)
$calc_purge_lots = explode ("-", $date_jour);
$annee_purge = $calc_purge_lots[0];
$mois_purge = $calc_purge_lots[1];
$jour_purge = $calc_purge_lots[2];

// Calcul de la date de purge des lots non mis en carton
$date_purge_lots = date ("Y-m-d", mktime (0, 0, 0, $mois_purge, $jour_purge + 10, $annee_purge));

// On boucle sur tout les codes barre
for ($i = 0; $i < $nb_codebarre; $i++)
{
  // On vérifie que le code barre n'est pas vide
  if ($codebarre[$i] != "")
  {
    // Colcul de la longueur de chaine de code barre et nettoyage des espaces en début et fin de chaine
    $codebarre[$i] = trim ($codebarre[$i]);
    // Gestion du code barre sur la longueur en fonction du n° de lot sur 1 ou  2 ou 3 caractères, on ajoute les 0
    // De cette manière peu importe la longueur initiale, on récupére le quantième toujours au même position
    $codebarre[$i] = str_pad($codebarre[$i], 19, "0");

    // Extrait du quantieme (jour dans l'année) à partir du code barre
    $quantieme_codebarre = substr ($codebarre[$i], 12, 3);

    // Colcul de la longueur de chaine de code barre suivant  et nettoyage des espaces en début et fin de chaine
    $codebarre[$i + 1] = trim ($codebarre[$i + 1]);

    // Gestion du code barre sur la longueur en fonction du n° de lot sur 1 ou  2 ou 3 caractères, on ajoute les 0
    // De cette manière peu importe la longueur initiale, on récupére le quantième toujours au même position
    $codebarre[$i + 1] = str_pad($codebarre[$i + 1], 19, "0");

    // Extrait du quantieme (jour dans l'année) à partir du code barre suivant
    $quantieme_codebarre_suivant = substr (($codebarre[$i + 1]), 12, 3);

    // Extrait de l'année à partir du code barre
    $annee_codebarre = substr ($codebarre[$i], 15, 4);

    // Nettoyage des espaces
    $codebarre_propre = preg_replace ('/\s{1,}/', '', $codebarre[$i]);

    // On vérifie que le lot est bien présent en base avant de faire un update (num_liaison est défini en index dans la table). Pour info, la table contient plus de 650 000 enregistrement format MyIsam.
    $query_verif_lot = "SELECT num_liaison FROM etj420 WHERE num_liaison  = '".mysql_real_escape_string($codebarre_propre)."'";
    $result_verif_lot = mysql_query ($query_verif_lot) or die
                        ('Erreur dans la requête : '.
                        $query_verif_lot.
                        '<br>Avec l\'erreur : '.
                        mysql_error ());
    $nb_verif_lot = mysql_numrows ($result_verif_lot);

    // Le lot est bien présent
    if ($nb_verif_lot > 0)
    {
      // On vérifie qu'on a pas déjà mis le lot en carton
      $query_verif_carton = "SELECT num_liaison, code_site, num_carton
                            FROM etj420
                            WHERE num_liaison = '".mysql_real_escape_string($codebarre_propre)."' AND
                            code_site = '".mysql_real_escape_string($_SESSION['codesite'])."' AND
                            num_carton != 0";
      $result_verif_carton = mysql_query ($query_verif_carton) or
                              die ('Erreur dans la requête : '.$query_verif_carton.
                             '<br>Avec l\'erreur : '.mysql_error ());
      $nb_verif_carton = mysql_numrows ($result_verif_carton);

      if ($nb_verif_carton == 0)
      {
        //On met à jour la table archive pour le n° de carton et le n° de travé en fonction du numliaison
        $query_maj_archive = "UPDATE etj420
                              SET
                                num_carton = '".mysql_real_escape_string($num_carton)."',
                                code_site = '".mysql_real_escape_string($_SESSION['codesite'])."'
                              WHERE
                                num_liaison  = '".mysql_real_escape_string($codebarre_propre)."'";

        /*
         * D'où vient $num_carton ?
         */
        $result_maj_archive = mysql_query ($query_maj_archive) or
                              die ('Erreur dans la requête : '.$query_maj_archive.
                                   '<br>Avec l\'erreur : '.mysql_error ());
      }
      else
      {
        $lots_deja_encarton. = $codebarre_propre." ";
      }
    }
    // Le lot n'est pas présent, on stocke son n°
    else
    {
      // Nettoyage des espaces
      $lots_non_present. = $codebarre_propre." ";
    }

    // On compare les 2 quantiemes, si ils sont différents, il faudra mettre à jour également la date de mise en carton et date d'épuration pour les 2 quantiemes
    if ($quantieme_codebarre != $quantieme_codebarre_suivant)
    {
      // On met à jour la table avec la date de mise en carton + la date d'épuration pour le quantieme du site
      $query_maj_carton = "UPDATE etj420
                          SET
                            date_mise_encarton='".mysql_real_escape_string($date_jour)."',
                            date_purge_lots='".mysql_real_escape_string($date_purge_lots)."'
                          WHERE
                            quantieme ='".mysql_real_escape_string($quantieme_codebarre)."' AND
                            annee='".mysql_real_escape_string($annee_codebarre)."' AND
                            code_site='".mysql_real_escape_string($_SESSION['codesite'])."'";
      $result_maj_carton =
        mysql_query ($query_maj_carton) or
        die ('Erreur dans la requête : '.$query_maj_carton.
       '<br>Avec l\'erreur : '.mysql_error ());
    }
    else
    {
      // On met à jour la table avec la date de mise en carton + la date d'épuration pour le quantieme suivant du site
      $query_maj_carton = "UPDATE etj420
                          SET
                            date_mise_encarton='".mysql_real_escape_string($date_jour)."',
                            date_purge_lots='".mysql_real_escape_string($date_purge_lots)."'
                          WHERE
                            quantieme ='".mysql_real_escape_string($quantieme_codebarre_suivant)."' AND
                            annee='".mysql_real_escape_string($annee_codebarre)."' AND
                            code_site='".mysql_real_escape_string($_SESSION['codesite'])."'";
      $result_maj_carton =
        mysql_query ($query_maj_carton) or
        die ('Erreur dans la requête : '.$query_maj_carton.
       '<br>Avec l\'erreur : '.mysql_error ());
    }
  }       // Fin du IF si le code barre n'est pas vide
}       // Fin du FOR


Re: Optimisation code

Posté : 09 nov. 2010, 12:44
par ouckileou
J'ai regardé vite fait mais cette page n'a pas l'air si lourde que ça je trouve.

Avant de chercher à optimiser niveau performance, je chercherais à optimiser niveau lisibilité. Par exemple, utiliser des constantes "POSITION_TRUC" plutôt que des nombres, utiliser des fonctions telles que "String extraireQuantieme(String codeBarre)" plus parlante et qui découpent le code, utiliser des foreach avec des variables explicites plutôt que des tableaux et indices, qui peuvent parfois perdre le lecteur. Et pourquoi la date est-elle stockée dans un fichier de configuration, tu ne peux pas la récupérer dynamiquement ?

Cela te permettrait de cibler facilement les opérations en cas de maintenance, factoriser ton code (tu fais deux fois les mêmes formatages sur codeBarre N et codeBarre N+1).

Petite remarque aussi :
     if ($longueur_codebarre == 17) {
        // On ajoute 2 zéro à num_lot
        $codebarre[$i] = substr_replace($codebarre[$i],"00",9,0);
     } else if ($longueur_codebarre == 18) {
    // On ajoute 1 zéro à num_lot
       $codebarre[$i] = substr_replace($codebarre[$i],"0",9,0); 
    } else {
       $codebarre[$i] = $codebarre[$i]; // bloc inutile
    }
Les deux premiers blocs (if et else if) peuvent être remplacés par l'utilisation de sprintf qui complète toute seule avec des zéros :
<?php
$cb1='12345678901234'; // longueur 17
$cb2='123456789012345678';
$cb3='1234567890123456789';

echo "longueur : ".strlen($cb1); echo '<br />';
echo sprintf("%'0-19s",$cb1); echo '<br /><br />';
echo "longueur : ".strlen($cb2); echo '<br />';
echo sprintf("%'0-19s",$cb2); echo '<br /><br />';
echo "longueur : ".strlen($cb3); echo '<br />';
echo sprintf("%'0-19s",$cb3); echo '<br /><br />';
?>
Une fois le code plus léger, je pense que tu pourras t'attaquer à l'aspect requêtes SQL, car c'est là que ça doit être consommateur de ressources. Si j'ai bien lu avec 60 code-barres, tu as (1 SELECT (ou deux) + 2 UPDATE) * 60 = 180 (ou 240 requêtes). C'est beaucoup, tu pourrais par exemple un système pour n'exécuter les updates qu'à la fin, en une seule fois.

Edit: en fait j'ai mal lu pour le nombre de requêtes mais il reste à mon avis important, ça reste "requêtes dans boucles" ce qui peut généralement être évité :)
Aussi : ton mysql_num_rows peut-être remplacé par un COUNT(colonne) dans la requête. Tout ça peut jouer sur tes perfs.

Et je vois que jojolapine a fait quelques remarques identiques :)

Re: Optimisation code

Posté : 09 nov. 2010, 14:31
par Gaara37
J'ai regardé vite fait mais cette page n'a pas l'air si lourde que ça je trouve.

Avant de chercher à optimiser niveau performance, je chercherais à optimiser niveau lisibilité. Par exemple, utiliser des constantes "POSITION_TRUC" plutôt que des nombres, utiliser des fonctions telles que "String extraireQuantieme(String codeBarre)" plus parlante et qui découpent le code, utiliser des foreach avec des variables explicites plutôt que des tableaux et indices, qui peuvent parfois perdre le lecteur. Et pourquoi la date est-elle stockée dans un fichier de configuration, tu ne peux pas la récupérer dynamiquement ?

Cela te permettrait de cibler facilement les opérations en cas de maintenance, factoriser ton code (tu fais deux fois les mêmes formatages sur codeBarre N et codeBarre N+1).

Petite remarque aussi :
     if ($longueur_codebarre == 17) {
        // On ajoute 2 zéro à num_lot
        $codebarre[$i] = substr_replace($codebarre[$i],"00",9,0);
     } else if ($longueur_codebarre == 18) {
    // On ajoute 1 zéro à num_lot
       $codebarre[$i] = substr_replace($codebarre[$i],"0",9,0); 
    } else {
       $codebarre[$i] = $codebarre[$i]; // bloc inutile
    }
Les deux premiers blocs (if et else if) peuvent être remplacés par l'utilisation de sprintf qui complète toute seule avec des zéros :
<?php
$cb1='12345678901234'; // longueur 17
$cb2='123456789012345678';
$cb3='1234567890123456789';

echo "longueur : ".strlen($cb1); echo '<br />';
echo sprintf("%'0-19s",$cb1); echo '<br /><br />';
echo "longueur : ".strlen($cb2); echo '<br />';
echo sprintf("%'0-19s",$cb2); echo '<br /><br />';
echo "longueur : ".strlen($cb3); echo '<br />';
echo sprintf("%'0-19s",$cb3); echo '<br /><br />';
?>
Une fois le code plus léger, je pense que tu pourras t'attaquer à l'aspect requêtes SQL, car c'est là que ça doit être consommateur de ressources. Si j'ai bien lu avec 60 code-barres, tu as (1 SELECT (ou deux) + 2 UPDATE) * 60 = 180 (ou 240 requêtes). C'est beaucoup, tu pourrais par exemple un système pour n'exécuter les updates qu'à la fin, en une seule fois.

Edit: en fait j'ai mal lu pour le nombre de requêtes mais il reste à mon avis important, ça reste "requêtes dans boucles" ce qui peut généralement être évité :)
Aussi : ton mysql_num_rows peut-être remplacé par un COUNT(colonne) dans la requête. Tout ça peut jouer sur tes perfs.

Et je vois que jojolapine a fait quelques remarques identiques :)
Salut et merci !

Je ne comprends pas bien pour le "sprintf", car je dois ajouter les 0 dans le n° en fonction de la longueur de la chaine, et non à la fin... Peux-tu m'en dire plus ?
Comment mettre les requêtes or de la boucle puisque je dois contrôler chaque numéro ?
Je fais les modifs et je cherche.

@+ tard

Re: Optimisation code

Posté : 09 nov. 2010, 14:40
par ouckileou
Est-ce que tu as testé le code fourni ?

Si on a bien compris, tu dois compléter a chaîne "code-barre" jusqu'à une longueur de 19 caractères, c'est ce que fait ce code
<?php
$cb1='12345678901234'; // longueur 1

echo "longueur : ".strlen($cb1); echo '<br />';
echo sprintf("%'0-19s",$cb1); echo '<br /><br />'; // '0 pour dire d'ajouter des zéros et non des espaces (par défaut), jusqu'à une longueur de 19, le - dit "à droite". %s signifie chaîne de caractère. 
?>
 
Tu peux aussi essayer la fonction de jojolapine, qui fera pareil mais t'éviteras d'avoir des if. En fait la sienne est même plus simple.

Après pour tes requêtes en fait il doit y avoir un aspect métier que nous ne connaissons pas, c'est quoi un quantième, et pourquoi tu compares les code-barres deux par deux ?

Re: Optimisation code

Posté : 09 nov. 2010, 14:45
par ouckileou
Ok on a mal compris je croyais que tu devais allonger la chaîne avec des zéros.

Bon tu peux oublier ça mais vraiment découper/réorganiser ton code, avec des fonctions, et des constantes pour stocker les indices (genre "INDICE_DEBUT_QUANTIEME") ça sera déjà plus facile à manipuler, je trouve.

Re: Optimisation code

Posté : 09 nov. 2010, 14:47
par AB
Oui aère et structure mieux ton code. Jojolapine t'a donné un exemple plus lisible.

Et puis pour des requêtes dans une boucle -> requêtes préparées.

Re: Optimisation code

Posté : 09 nov. 2010, 15:27
par gaara37
Oui aère et structure mieux ton code. Jojolapine t'a donné un exemple plus lisible.

Et puis pour des requêtes dans une boucle -> requêtes préparées.

Ok, je vais déjà mettre mon code plus claire.
Requêtes préparées, je ne vois vraiment pas => Peux-tu m'en dire plus ?

Je te remercie !!

@+ tard

Re: Optimisation code

Posté : 09 nov. 2010, 15:47
par jojolapine
@gaara37:
exemple de requête préparée via pdo: http://fr2.php.net/manual/fr/pdo.prepare.php

Le principe, c'est que tes requêtes sont gardées en mémoire (ds le détail je sais plus trop où m'enfin c'est pas le sujet ici ;) )...
Le "parsage" de ta requête via mysql ne sera donc fait qu'une fois...
Si on me pardonne l'abus de langage, on peut dire que ta requête est "pré-compilée"
Les appels suivants seront donc plus rapides :)

Re: Optimisation code

Posté : 09 nov. 2010, 16:42
par AB
Tu peux faire des requêtes préparées également avec mysqli http://www.php.net/manual/fr/mysqli-stmt.prepare.php (en mode procédural c'est très ressemblant avec mysql si ça peut t'aider).

Il me semble aussi que tu peux faire des requêtes préparées avec mysql mais j'ai perdu le lien.


Ah oui et le lien qui explique l'intérêt de faire des requêtes préparée http://php.net/manual/fr/pdo.prepared-statements.php
La plupart des bases de données supportent le concept des requêtes préparées. Qu'est-ce donc ? Vous pouvez les voir comme une sorte de modèle compilé pour le SQL que vous voulez exécuter, qui peut être personnalisé en utilisant des variables en guise de paramètres. Les requêtes préparées offrent deux fonctionnalités essentielles :

* La requête ne doit être analysée (ou préparée) qu'une seule fois, mais peut être exécutée plusieurs fois avec des paramètres identiques ou différents. Lorsque la requête est préparée, la base de données va analyser, compiler et optimiser son plan pour exécuter la requête. Pour les requêtes complexes, ce processus peut prendre assez de temps, ce qui peut ralentir vos applications si vous devez répéter la même requête plusieurs fois avec différents paramètres. En utilisant les requêtes préparées, vous évitez ainsi de répéter le cycle analyser/compilation/optimisation. Pour résumer, les requêtes préparées utilisent moins de ressources et s'exécutent plus rapidement.

Re: Optimisation code

Posté : 10 nov. 2010, 11:21
par Gaara37
Bonjour à tous,

Je reviens vers vous car j'ai modifié mon code en suivant vos conseils et en essayant les requêtes préparées. Je ne constate aucune amélioration du temps de réponse. Peut-être que j'ai mal pigé l'utilisation des requêtes préparées, donc voici le code source :
// Appel de la fonction num carton
$carton = carton($_POST['numcarton']);
// Calcul de la longueur du n° carton pour ne pas concaténer à chaque fois le code site
$longueur = strlen($carton);
if ($longueur <= 4) {
	// On concaténe le code site avec le n° de carton afin de déterminer sur quel site a été fait le carton
	$num_carton = $_SESSION['codesite'].$carton;
}
/******************  Préparation des requêtes pour accélérer le traitement ******************/

// Requête de vérification du num_liaison
$prepare_numliaison = "PREPARE verif_numliaison FROM 'select num_liaison from etj420 where (num_liaison = ?)'"; 
mysql_query($prepare_numliaison) or exit("<br>ERREUR PREPARE:<br> $prepare_numliaison".mysql_error());

// Requête de vérification si le lot est déjà en carton par rapport au site.
$prepare_verif_carton = "PREPARE verif_encarton FROM 'select num_liaison, code_site, num_carton from etj420 where (num_liaison  = ? and code_site = $_SESSION[codesite] and num_carton != 0)'";
mysql_query($prepare_verif_carton) or exit("<br>ERREUR PREPARE:<br> $prepare_verif_carton".mysql_error());

// Mise à jour des lots en carton
$prepare_mise_encarton = "PREPARE mise_encarton FROM 'update etj420 set num_carton = $num_carton, code_site = $_SESSION[codesite] where (num_liaison  = ?)'";
mysql_query($prepare_mise_encarton) or exit("<br>ERREUR PREPARE:<br> $prepare_mise_encarton".mysql_error());

// Mise à jour quantieme different
$prepare_quantieme_diff = "PREPARE quantieme_diff FROM 'update etj420 set date_mise_encarton = now(), date_purge_lots = ? where (quantieme = ? and annee= ? and code_site=$_SESSION[codesite])'";
mysql_query($prepare_quantieme_diff) or exit("<br>ERREUR PREPARE:<br> $prepare_quantieme_diff".mysql_error());

// Mise à jour quantieme identique
$prepare_quantieme = "PREPARE quantieme_identique FROM 'update etj420 set date_mise_encarton = now(), date_purge_lots = ? where (quantieme = ? and annee= ? and code_site=$_SESSION[codesite])'";
mysql_query($prepare_quantieme) or exit("<br>ERREUR PREPARE:<br> $prepare_quantieme".mysql_error());

/******************  Fin préparation des requêtes pour accélérer le traitement ******************/

// On vérifie la valeur du Input pour savoir si on est sur une fin de carton ou fin de quantieme

	

			// Récupération des différents codebarre(numliaison)
			$codebarre = explode (PHP_EOL,  trim  ($_POST['codebarre']));
			$nb_codebarre = count($codebarre);

			// Récupération pour la purge
			$annee_purge = date("Y");
			$mois_purge  = date("m");
			$jour_purge  = date("d");	

			// Calcul de la date de purge des lots non mis en carton
			$date_purge_lots = date("Y-m-d", mktime(0, 0, 0, $mois_purge, $jour_purge+10, $annee_purge));
			
			// On boucle sur tout les codes barre
			for($i=0;$i<$nb_codebarre;$i++) 
			{
				// On vérifie que le code barre n'est pas vide
				if ($codebarre[$i] != "") 
				{
					// Fonction colcul de la longueur de chaine de code barre et nettoyage des espaces en début et fin de chaine
					$codebarre[$i] = calcul_codebarre(trim($codebarre[$i]));

					// Fonction pour extraire le quantième
					$quantieme_codebarre = extrait_quantieme($codebarre[$i]);
					// Extrait de l'année à partir du code barre
					$annee_codebarre = substr($codebarre[$i],15,4);	
					
					// Fonction colcul de la longueur de chaine de code barre et nettoyage des espaces en début et fin de chaine
					$codebarre_suivant[$i+1] = calcul_codebarre($codebarre[$i+1]);
					// Fonction pour extraire le quantième
					$quantieme_codebarre_suivant = extrait_quantieme($codebarre_suivant[$i+1]);
					
					//print "$codebarre[$i],$quantieme_codebarre,$annee_codebarre".$codebarre_suivant[$i+1]."$quantieme_codebarre_suivant<br />";
					
					// Execution de la 1ère requête
					$query_numliaison = "SET @num_liaison='".$codebarre[$i]."'";
					mysql_query($query_numliaison) or exit("<br>ERREUR SET:<br>".mysql_error());
					$sql_numliaison = "EXECUTE verif_numliaison USING @num_liaison";
					$res_numliaison = mysql_query($sql_numliaison) or exit("<br>ERREUR EXECUTE:<br>".mysql_error());
					$nb_verif_lot = mysql_numrows($res_numliaison);
						// Le lot est bien présent
						if ($nb_verif_lot > 0) 
						{	
							// Execution de la 2ème requête
							$query_encarton = "SET @num_liaison='".$codebarre[$i]."'";
							mysql_query($query_encarton) or exit("<br>ERREUR SET:<br>".mysql_error());
							$sql_encarton = "EXECUTE verif_encarton USING @num_liaison";
							$res_encarton = mysql_query($sql_encarton) or exit("<br>ERREUR EXECUTE:<br>".mysql_error());
							$nb_verif_carton = mysql_numrows($res_encarton);
							if ($nb_verif_carton == 0) 
							{
								// Exécution de la 3ème requête
								$query_update = "SET @num_liaison='".$codebarre[$i]."'";
								mysql_query($query_update) or exit("<br>ERREUR SET:<br>".mysql_error());
								$sql_query_update = "EXECUTE mise_encarton USING @num_liaison";
								$res_query_update = mysql_query($sql_query_update) or exit("<br>ERREUR EXECUTE:<br>".mysql_error());
							}
							else 
							{
								$lots_deja_encarton .= $codebarre[$i]." ";
							}
						}
						// Le lot n'est pas présent, on stocke son n°
						else 
						{	
							$lots_non_present .= $codebarre[$i]." ";
						}
						// On compare les 2 quantiemes, si ils sont différents, il faudra mettre à jour également la date de mise en carton et date d'épuration pour les 2 quantiemes
						if ($quantieme_codebarre != $quantieme_codebarre_suivant) 
						{
							// Exécution de la 4ème requête
							$query_update_quantieme = "SET @date_purge_lots='".$date_purge_lots."', @quantieme='".$quantieme_codebarre."', @annee='".$annee_codebarre."'";
							mysql_query($query_update_quantieme) or exit("<br>ERREUR SET:<br>".mysql_error());
							$sql_update_quantieme = "EXECUTE quantieme_diff USING @date_purge_lots, @quantieme, @annee";
							$res_update_quantieme = mysql_query($sql_update_quantieme) or exit("<br>ERREUR EXECUTE:<br>".mysql_error());
						} 
						else 
						{
							// Exécution de la 5ème requête
							$query_update_quantieme = "SET @date_purge_lots='".$date_purge_lots."', @quantieme='".$quantieme_codebarre_suivant."', @annee='".$annee_codebarre."'";
							mysql_query($query_update_quantieme) or exit("<br>ERREUR SET:<br>".mysql_error());
							$sql_update_quantieme = "EXECUTE quantieme_identique USING @date_purge_lots, @quantieme, @annee";
							$res_update_quantieme = mysql_query($sql_update_quantieme) or exit("<br>ERREUR EXECUTE:<br>".mysql_error());
						}
				}
			}
Je pense que j'ai du rater quelque chose... Pouvez-vous me donner un ptit coup de main ? Pour info, je ne peux pas utliser PDO. Ce que j'ai du mal à comprendre, c'est que la boucle peut comporter au maximum 60 itérations, ce qui n'est pas énorme.
Merci.
@+ tard

Re: Optimisation code

Posté : 10 nov. 2010, 11:28
par ouckileou
C'est possible que le problème soit ailleurs, après tout tu as dit que le serveur n'était pas optimisé, qu'est-ce que tu entends par là ?

Et puis, pourquoi dois-tu travailler les performances, les utilisateurs se plaignent de temps de réponse trop longs mais dans les faits, qu'est-ce que ça veut dire ? Tu as fais des mesures, des tests ? Il y des outils pour ça, au niveau de PHP ou de MySQL

Re: Optimisation code

Posté : 10 nov. 2010, 11:29
par stealth35
Pourquoi tu ne peu pas utilise PDO, t'as quelle version de php et t'es chez quel herbergeur ?

Re: Optimisation code

Posté : 10 nov. 2010, 11:38
par Gaara37
Pourquoi tu ne peu pas utilise PDO, t'as quelle version de php et t'es chez quel herbergeur ?
Je ne peux pas utiliser PDO car politique intérieur et je suis en Intranet. Je n'ai pas le pouvoir de décision sur certains paramètres !

Re: Optimisation code

Posté : 10 nov. 2010, 11:40
par stealth35
bon...

en tout cas les requête préparer comme t'as fait ne sont pas bonne, avec mysql_* oublie