Mysql Des SELECT à la chaine.

Résolu/Fermé
Mikamadgik Messages postés 87 Date d'inscription samedi 8 novembre 2008 Statut Membre Dernière intervention 26 avril 2021 - 29 août 2012 à 22:05
Mikamadgik Messages postés 87 Date d'inscription samedi 8 novembre 2008 Statut Membre Dernière intervention 26 avril 2021 - 30 août 2012 à 20:21
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

arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 1 291
30 août 2012 à 02:21
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
Mikamadgik Messages postés 87 Date d'inscription samedi 8 novembre 2008 Statut Membre Dernière intervention 26 avril 2021 1
30 août 2012 à 08:13
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
kalamit Messages postés 278 Date d'inscription samedi 10 juin 2006 Statut Contributeur Dernière intervention 29 juin 2016 16
30 août 2012 à 10:48
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
Mihawk Messages postés 4313 Date d'inscription mercredi 29 mars 2006 Statut Contributeur Dernière intervention 6 janvier 2015 845
30 août 2012 à 10:54
Hello,

C'est pas gérable avec des jointures comme requête ?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
maka54 Messages postés 699 Date d'inscription mercredi 8 avril 2009 Statut Membre Dernière intervention 4 décembre 2016 80
30 août 2012 à 13:27
çà doit pouvoir se faire en une requete

il faudrait voir a quoi ressemble la base de données , les liens entre les tables
0
Mikamadgik Messages postés 87 Date d'inscription samedi 8 novembre 2008 Statut Membre Dernière intervention 26 avril 2021 1
30 août 2012 à 20:21
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