Aller au contenu
  • Pas encore inscrit ?

    Pourquoi ne pas vous inscrire ? C'est simple, rapide et gratuit.
    Pour en savoir plus, lisez Les avantages de l'inscription... et la Charte de Zébulon.
    De plus, les messages que vous postez en tant qu'invité restent invisibles tant qu'un modérateur ne les a pas validés. Inscrivez-vous, ce sera un gain de temps pour tout le monde, vous, les helpeurs et les modérateurs ! :wink:

Problème sur boucle while très longue


mediaforest

Messages recommandés

J'ai un problème avec un script destiné à analyser les visites d'un site.

A chaque ouverture d'une page une entrée est ajoutée dans une table MySQL avec l'id de la page, la date et la langue.

Depuis 2009, j'ai accumulé 4778413 entrées dans cette table.

Mon script affiche le nombre d'affichages de chaque page pour un intervale de dates donné.

Pour des intervales de un à 6 mois ça fonctionne très bien et c'est relativement rapide malgré les quelques 930000 résultats trouvés pour 6 mois.

Par contre pour des intervales plus longs, ma boucle s'interrompt sans fournir le moindre message d'erreur de timeout ou de mémoire.

J'ai tracé mon script sous débogueur pas à pas et la requête MySQL se déroule correctement, c'est bien ma boucle qui s'arrête sans prévenir.

Voici le code utilisé :

    
   // utilisation d'une fonction de conversion de jj/mm/aaaa en aaaa-mm-jj
   $date_debut = Date_aaaammjj($date_min);
   $date_fin = Date_aaaammjj($date_max);

   // tout récupérer
   $query = "SELECT * FROM Stats_pages_vues WHERE date>=\"".$date_debut." 00:00:00\" AND date<=\"".$date_fin." 23:59:59\"";
   $req = mysql_query($query);
   $nbre_result = mysql_num_rows($req);
   $tout = array();

   //for($i=1; $i<= $nbre_result; $i++) {
   while($c = mysql_fetch_array($req)) {
       $c = mysql_fetch_array($req);
       $tout[] = $c["id_page"];   
   } 
   $somme = array_count_values($tout);
   arsort($somme);

Comme vous pouvez le voir j'ai essayé avec une boucle for et avec une boucle while, avec exactement les mêmes symptômes.

J'ai essayé de modifier la directive memory_limit par ini_set('memory_limit','1024M'), mais en contrôlant avec phpinfo(4); la valeur refuse de changer et je ne comprends pas pourquoi.

J'ai modifié la directive max_execution_time par ini_set('max_execution_time','240'), dans ce cas la modif est prise en compte mais mon script s'arrête toujours sans rien dire.

 

J'ai essayé de reconstruire mon script en recherchant d'abord les id de pages distincts avant de dénombrer les affichages pour chaque page, mais dans ce cas l'exécution est extrèmement longue.

 

Est-ce que l'un d'entre vous pourrait me guider, parce que là je tourne en rond avec ce problème.

Merci d'avance.

Lien vers le commentaire
Partager sur d’autres sites

salut,

 

Je ne connais pas vraiment php, ce n'est pas vraiment sur le contenu de ton script que je voulais intervenir mais parce qu'une chose me semble étrange :

A chaque appel a la fonction mysql_fetch_array tu fetch une ligne c'est ca?

Du coup la tu recupère 1 ligne pour 2 fetch, non? (1 dans le controle du while et 1 dans la boucle)

 

Désolé si je comprend mal, c'est pour aider :)

Lien vers le commentaire
Partager sur d’autres sites

  • Modérateurs

Bonjour mediaforest, ju&ges,

 

Bonne remarque, ju&ges ! En effet, cette séquence lit successivement deux lignes, une dans le while, et une sur la ligne d'assignation qui suit. La première sera donc ignorée. Du coup, si la sélection contient un nombre n de lignes impair, la tentative de lecture (non protégée) de la (n+1)ème ligne risque de perturber le fonctionnement de l'algorithme. À mon avis, la seconde ligne est de trop, et il suffit de l'enlever… À tester ;)

 

//for($i=1; $i<= $nbre_result; $i++) {

while($c = mysql_fetch_array($req)) {

$c = mysql_fetch_array($req);

$tout[] = $c["id_page"];

}

Lien vers le commentaire
Partager sur d’autres sites

merci dylav,

 

En fait en y reflechissant aprés je me disais que le plus simple c'etait peut être de le faire dans mysql dans le genre une requête :

 

 $query = "SELECT count(*), id_page  FROM Stats_pages_vues WHERE date>=\"".$date_debut." 00:00:00\" AND date<=\"".$date_fin." 23:59:59\" group by id_page ";

 

Ca t'evite la boucle.

Lien vers le commentaire
Partager sur d’autres sites

L'idée c'etait de compter le nombre de fois ou chaque "id_page" apparaissaient d'ou le "group by" et pas le nombre de ligne de son tableau ramenait.

J'avais cru comprendre que c'etait le but de sa demande mais c'est vrai que je n'avais pas fait attention qu'il ramenait tout :outch:

Désolé :)

Lien vers le commentaire
Partager sur d’autres sites

Bonjour à tous et merci pour vos réponses.

En fait je me suis planté en recopiant mon code source :

Dans le cas de la boucle while, le fetch_array se fait uniquement sur la ligne :

while($c = mysql_fetch_array($req))

 

La ligne $c = mysql_fetch_array($req); ne sert que pour la boucle for

 

Je ne fais donc qu'un fetch_array par boucle.

 

Même si ça ne m'étonne pas que la mémoire puisse être saturée étant donné le grand nombre d'itération ( plus d'1 million )

ce que je ne comprends pas c'est pourquoi php ne m'envoie pas un message d'erreur.

Lien vers le commentaire
Partager sur d’autres sites

  • Modérateurs

Bonjour mediaforest,

 

Ton $c = mysql_fetch_array($req); était peut-être à l'origine associé à la boucle for, mais cette boucle n'existe plus (la ligne est en commentaire), donc ton script, dans l'état où tu nous le montres, comporte bien deux lectures pour un seul examen… ;)

 

Quant à la saturation de la mémoire, c'est quasiment une certitude. Je suis comme toi surpris que n'apparaisse aucun message d'erreur au moment de cette saturation ? À moins que tu n'aies, volontairement ou pas, demandé une désactivation des aletres (à supposer que ce paramétrage soit possible)… :chpas:

Lien vers le commentaire
Partager sur d’autres sites

Rejoindre la conversation

Vous pouvez publier maintenant et vous inscrire plus tard. Si vous avez un compte, connectez-vous maintenant pour publier avec votre compte.
Remarque : votre message nécessitera l’approbation d’un modérateur avant de pouvoir être visible.

Invité
Répondre à ce sujet…

×   Collé en tant que texte enrichi.   Coller en tant que texte brut à la place

  Seulement 75 émoticônes maximum sont autorisées.

×   Votre lien a été automatiquement intégré.   Afficher plutôt comme un lien

×   Votre contenu précédent a été rétabli.   Vider l’éditeur

×   Vous ne pouvez pas directement coller des images. Envoyez-les depuis votre ordinateur ou insérez-les depuis une URL.

  • En ligne récemment   0 membre est en ligne

    • Aucun utilisateur enregistré regarde cette page.
×
×
  • Créer...