Mysql Des SELECT à la chaine.

Résolu
Mikamadgik Messages postés 98 Statut Membre -  
Mikamadgik Messages postés 98 Statut Membre -
Bonjour,
J'utilise phpmyadmin avec un serveur ovh, et j'ai un calcul a sortir, qui marche trés bien sur mon ordi, mais quand elle est en ligne, celle-ci est tellement longue quel ne s'ouvre même pas (elle calcul environ 400000 résultat) mais n'en affichera que trés peu (3 à 4 résultats).

400 000 résultat parce que c'est un SELECT dans un autre SELECT dans un autre SELECT dans une boucle... et ca va trés vite! J'ai beau chercher des système de jonction pour remplacer tous ces SELECT par une seul requet, mais je ne trouve pas. Quelqu'un aurait il une piste pour m'orienter? Merci d'avance.

PS: Je ne suis que novice dans le domaine.

Voici mon code:

// debut de la recherche des articles
include ("connect.php");
$get44 = mysql_query("SELECT id, quantite_stock, description, dimension FROM ".$stock."");
mysql_close($connect);
while ($row3 = mysql_fetch_assoc($get44))
{
$idmatos = $row3['id'];
$stockmatos = $row3['quantite_stock'];
$titrematos = $row3['description'];
$dimmatos = $row3['dimension'];
// tous les documents de l'articles sont en stock
$dateinit = $datedebut; // j'initialise la date
while ($dateinit <= $datefin )
{
// je regarde parmis ces date se qu'il y a
// première chose, quel spectacle?
include ("connect.php");
$get45 = mysql_query("SELECT id FROM ".$secteur." WHERE (date_fin>='$datedebut' && date_debut<='$datefin'))"); // j'ai rajouté cette option d'etat pour essayé d'accéléré l'ouverture de la page, mais pas sur que ca marche))
mysql_close($connect);
// pour tous les spectacle présent:
while ($row4 = mysql_fetch_assoc($get45))
{
$idspectacle = $row4['id'];
$total = "0";
// recherche des produits utilisé lors de cette journée.
include ("connect.php");
$get46 = mysql_query("SELECT quantite_prevu, quantite_retour FROM ".$liens." WHERE spectacle='$idspectacle' && materiel='$idmatos'");
mysql_close($connect);
while ($row5 = mysql_fetch_assoc($get46))
{
$soustotal = "0";
$soustotalutilise = $row5['quantite_prevu'];
$soustotalretour = $row5['quantite_retour'];
$total = $total + ($soustotalutilise - $soustotalretour);
//$total total d'article X utilisé par ce spectacle
}
// $total2 d'article utilisé par tous les spectacles ce jour
$total2 = $total + $total2;
mysql_free_result($get46);
}
// total3 d'article utilisé par tous les spectacles durant tous les jours
if ($total2>$total3)
{$total3 = $total2;}
else{}

$total2 = "0";
$tmp = explode("-", $dateinit);
$dateinit = date("Y-m-d",mktime(0,0,0,$tmp[1],$tmp[2]+1,$tmp[0]));
mysql_free_result($get45);
}
$restant = $stockmatos - $total3;
$total3 = "0";
if ($restant < 0)
{

?>
// partie de l'édition de la ligne.

<?php

}
else {}

}
mysql_free_result($get44);

6 réponses

  1. arth Messages postés 84 Date d'inscription   Statut Contributeur Dernière intervention   1 296
     
    Hello,

    Un serveur dédié ou un serveur mutualisé? La puissance d'un mutualisé est quand même moindre qu'un dédié.

    Ensuite, le code est un poil brouillon, mais bon tout ne peut être parfait au début :-)

    Normalement on utilise des pages différentes ou avec des options dans les URL pour réduire la recherche, ou pour rechercher des éléments différents.

    Petit tips, je ne pense pas qu'il y ait d'intérêt à inclure 4256,3 fois la page connect.php. Normalement une seule inclusion au début du code est suffisante.

    Pour le reste, sans savoir ce que fais exactement ce code, pourrais-tu détailler :

    - Quelles sont les tables utilisées?
    - Quels sont les différents champs des tables?
    - Quelles informations le code mis est-il censé chercher ?

    Tel quel, j'ai l'impression que la page fait trop d'opérations en une seule fois.
    0
  2. Mikamadgik Messages postés 98 Statut Membre 1
     
    Hello,

    Merci pour ta réponse, j'utilise en effet un serveur mutualisé.
    J'aurais voulu en effet restreindre les recherches en mettant des options dans les "where", mais je ne peux pas plus, sinon mes résultats deviendrais faux.

    Le code sert à déterminé les besoins en location pendant les 2 prochaines semaines.

    $stock c'est la table du stock de la personne
    les colonnes: id, description, dimension, quantité_stock

    $secteur c'est la table des prestations
    les colonnes: id, titre, date_debut, heure_debut, date_fin, heure_fin

    Chaque prestas utilisent certains matériels, il y a donc une table de liens:
    $liens: table entre le spectacle, l'article, et la quantité
    les colonnes: id, spectacle, matériel, quantite_prévu, quantit_retour

    Donc a chaque fois qu'on veut rajouter du matériel a une presta, cela édite une ligne de la table $liens.

    La question de toute cette page est: Dans les 14 prochains jours manque t'il du matériel à un moment?

    Et donc sur mon code actuel sa donne:
    Une boucle pour les 14 jours
    a l'intérieur:
    selection de chaque article
    a l'interieur
    je regarde toutes les prestas à ce jour
    a l'interieur
    je recherche tous les liens correspondant a cette presta et cette article pour en additionner les quantité utilisé, et soustraire tous les retours si il y en a.
    Je prend le stock général de l'article, je soustrait ce que j'ai trouvé, si c'est < à 0, j'édite une ligne.

    Donc en fait mais boucle font
    Pour les jours x14
    Pour les articles env x120
    Pour les presta env x20
    Pour les liens env x30
    Ce qui fait un total d'environs 1 008 000 examen pour finalement 2, voir 3 résultats maximum.

    Merci d'avance pour tes idées
    0
  3. kalamit Messages postés 307 Statut Contributeur 17
     
    Salut,

    Première chose, peux tu reposter le code avec l'indentation (avec la balise "code"), juste pour plus de lisibilité.
    Ensuite je te suggère de tout regrouper au sein d'une requête unique avec des jointures externes.
    Enfin, je te suggère d'afficher en clair la requête que tu exécutes et de la passer dans un explain plan qui te montreras quels index tu dois ajouter pour éviter la full table scan.
    C'est la démarche standard d'optimisation d'une requête.

    Sur les perfs du serveur mutualisé, je ne pense pas que ce soit un problème pour l'instant.
    0
  4. Mihawk Messages postés 4753 Statut Contributeur 846
     
    Hello,

    C'est pas gérable avec des jointures comme requête ?
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. maka54 Messages postés 721 Statut Membre 80
     
    çà doit pouvoir se faire en une requete

    il faudrait voir a quoi ressemble la base de données , les liens entre les tables
    0
  7. Mikamadgik Messages postés 98 Statut Membre 1
     
    Sur vos conseils j'ai travaillé sur le système de jointure. Et bien je viens donc de modifier le code, et ça donne cela:

    <?php
    	 $statut = $_GET['sta'];
    	 include ("statut.php");
    	 
    	 
    	 $datedebut = date("Y-m-d");
    	 $datefin = date("Y-m-d",mktime(0,0,0,date("m"),date("d")+14,date("Y")));
    	 $heuredebut = date("H");
    	 $heurefin = $heuredebut + 1;
    	 $enposte = '20';
    	 $total3 ="0";
    	 	
    			             // debut de la recherche des articles
    						 include ("connect.php");
    						 $get44 = mysql_query("SELECT id, quantite_stock, description, dimension FROM ".$stock."");
    						 mysql_close($connect);
    		                 while ($row3 = mysql_fetch_assoc($get44)) 
    					                 {
    						              $idmatos = $row3['id'];
    			                          $stockmatos = $row3['quantite_stock'];
    						              $titrematos = $row3['description'];
    				    	              $dimmatos = $row3['dimension'];
    						              // tous les documents de l'articles sont en stock
    					                  $dateinit = $datedebut;  // j'initialise la date
    						              while ($dateinit <= $datefin)
    						                    {
    											 // je regarde parmis cette date se qui il y a
    											 // première chose, quel spectacle?
    											 $total = "0";
    											 include ("connect.php");
    						                      $get40 = mysql_query("SELECT ".$secteur.".id, quantite_prevu, quantite_retour, materiel FROM ".$secteur." JOIN ".$liens." ON ".$secteur.".id = ".$liens.".spectacle WHERE 
    					                                   (materiel='$idmatos') && 
    													   ((((".$secteur.".etat=".$enposte.") || ((".$secteur.".date_debut<'$dateinit') || 
    					                                   ((".$secteur.".date_debut='$dateinit') && ('$dateinit'='$datefin') && ('$heurefin'>".$secteur.".heure_debut)) ||
    					                                   ((".$secteur.".date_debut='$dateinit') && (!('$dateinit'='$datefin'))))
    					                                    && 
    					                                   ((".$secteur.".date_fin>'$dateinit') ||
    					                                   ((".$secteur.".date_fin='$dateinit') && ('$dateinit'='$datedebut') && ('$heuredebut'<".$secteur.".heure_fin)) ||
    					                                   ((".$secteur.".date_fin='$dateinit') && (!('$dateinit'='$datedebut')))))) && (".$secteur.".etat<'9' || ".$secteur.".etat>'13') || (".$secteur.".etat>'9' && ".$secteur.".etat<'13'))"); // j'ai rajouté cette option d'etat pour essayé d'accéléré l'ouverture de la page, mais pas sur que ca marche))
                                                                      while ($row5 = mysql_fetch_assoc($get40)) 
    					                                                                {
    																		             $soustotalutilise = $row5['quantite_prevu'];
    									                                                 $soustotalretour = $row5['quantite_retour'];
    									                                                 $total = $total + ($soustotalutilise - $soustotalretour);
    								                                                     }
    	                                                  //  total3 d'article utilisé par tous les spectacles durant tous les jours
    													  if ($total>$total3)
    													            {$total3 = $total;}
    													         else{}
    													
    													   $total = "0";	 
    													   $tmp = explode("-", $dateinit);
    						                               $dateinit = date("Y-m-d",mktime(0,0,0,$tmp[1],$tmp[2]+1,$tmp[0]));
    					 			            }
    									 $restant = $stockmatos - $total3;
    									 $total3 = "0";
    					                 if ($restant < 0)  
    											 {
    				                            
    ?>	                                			
    ici j'édite la ligne
    <?php	
    							  
    							                   }
    										       else {}	
    													  
    				                      }
    									  mysql_free_result($get44);
    							  
    ?>
    
    </body>
    </html>
    


    Je viens de la tester sur le serveur d'ovh et la requête à pris moins de 20 secondes! Parfait!! J'ai essayé de réduire un peu plus, mais je n'ai pas trouvé :s

    Je vous donne la base de données:
    Table spectacle
    id // titre // date_debut // date_fin // heure_debut // heure_fin
    Table stock
    id // description // dimension // quantité_stock
    Table liens
    id // spectacle (en lien avec spectacle.id) // materiel (en lien avec stock.id)// quantite_prevu // quantite_retour

    J'ai pas trouvé d'autre solution pour mettre la date a l'extérieur de la requête du matos, comme j'ai besoin de calculer par article :/.
    Si vous avez une idée n'hésitez pas mais pour moi le sujet est en partie résolu!
    0