[RESOLU] Lenteur a cause de 2 requetes

Petit nouveau ! | 3 Messages

30 nov. 2013, 03:24

Bonsoir à tous,

J'ai une petite question pour améliorer la rapidité d'affichage.
J'ai une requete qui va chercher environ 5000 données dans une table et je la met en forme dans un tableau. Mais à chaque ligne je réalise de nouveau une requête pour avoir des informations complèmentaires dans une autre table. Comment faire pour améliorer tout cela ?

Voici le code
<?php
if(isset($_SESSION['login']) && $_SESSION['login']!='')
{//Vérification qu'une session existe bien
	connect();
?>
<script type="text/javascript">
$(document).ready( function() 
{	
	//Mise en forme des résultat au format Datatable
	var oDataTable = $('#table_adh').dataTable({
		"bPaginate": false,
		"bJQueryUI": true,
		"bInfo": true,
		"bFilter":true,
	});
	
	//Action du click pour afficher la facebox
	$('a[rel*=action]').on("click", function() {
		$(this).unbind("click").facebox().trigger('click');
		return false;
	});
	
});
</script>
<h2>Liste des adh&eacute;rents</h2>
<?php
	//Requete sélection des adherents
	$req_adh = 'SELECT id_adh, nom_adh, prenom_adh, tel_adh, etat_adh FROM adherents ORDER BY id_adh ASC';
	$res_adh = mysql_query($req_adh);
?>
	<table align="center" width="100%" id="table_adh">
		<thead>
		<tr>
			<th>N&deg; Adh</th>
			<th>Nom</th>
			<th>Pr&eacute;nom</th>
			<th>T&eacute;l&eacute;phone</th>
			<th>Date Inscription</th>
			<th>Dur&eacute;e</th>
			<th>Montant</th>
			<th>Date de fin</th>
			<th>Etat</th>
			<th>&nbsp;</th>
		</tr>
		</thead>
		<tbody>
		
		<?php
		while($adherent = mysql_fetch_array($res_adh))
		{
		?>
		<tr align="center">
			<td><?php echo $adherent['id_adh'];?></td>
			<td><a href="?page=detail_adh&id=<?php echo $adherent['id_adh'];?>" class="action"><?php echo $adherent['nom_adh'];?></a></td>
			<td><a href="?page=detail_adh&id=<?php echo $adherent['id_adh'];?>" class="action"><?php echo $adherent['prenom_adh'];?></a></td>
			<td><?php echo $adherent['tel_adh'];?></td>
			<?php
			$sql_fact = 'SELECT DISTINCT id_fact, date_fact, duree_fact, montant_fact, id_adh_fact FROM facture WHERE id_adh_fact='.$adherent['id_adh'].' ORDER BY date_fact DESC LIMIT 1'; 
			$req_fact = mysql_query($sql_fact) or die('Erreur SQL !<br>'.$sql_fact.'<br>'.mysql_error());
			
			if(mysql_num_rows($req_fact)>0)
			{//Si on a un résultat
				while($facture = mysql_fetch_assoc($req_fact))
				{
					$date_facture_fr = explode('-',$facture['date_fact']);
				
					echo "<td>".$date_facture_fr[2].'/'.$date_facture_fr[1].'/'.$date_facture_fr[0]."</td>";
					echo "<td>".$facture['duree_fact']."</td>";
					echo "<td>".$facture['montant_fact']." &euro;</td>";
								
					$date_fin =  mktime(0,0,0, $date_facture_fr[1] + $facture['duree_fact'], $date_facture_fr[2], $date_facture_fr[0]);
					$date_fin_fr=date('d/m/Y',$date_fin);
					
					echo "<td>".$date_fin_fr."</td>";
				} 
			}
			else
			{
				echo "<td>0000/00/00</td>";
				echo "<td>0</td>";
				echo "<td>0</td>";			
				echo "<td>0000/00/00</td>";
			}
			?>
			<td><?php echo $adherent['etat_adh'];?></td>
			<td align="center">
				<a href="pages/adherents/modif_rapid_adherent.php?id=<?php echo $adherent['id_adh'];?>" rel="action" title="Modifier l'adh&eacute;rent rapidement">
				<span class="ui-state-default ui-corner-all ui-icon ui-icon-pencil"></span></a>
			</td>
		</tr>
		<?php
		}
		?>
		</tbody>
	</table>
<?php
}//Vérification qu'une session existe bien
?>
Merci d'avance :)

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

30 nov. 2013, 10:47

Salut,

Première optimisation : ne pas sélectionner 5k lignes c'est inutile personne ne regarde ça sur une page.
Par contre avec une pagination, voir la possibilité de trié / restreindre l'affichage est une meilleure idée.
Donc si tu te lumite a, par exemple, 20 enregistrements par page tu va limiter les dégâts.
Côté code tu utilise un while qui n'as pas lieu d'être vue que tu limite à un le nombre de ligne.
Dans le même tu utilise un distinct mais tu met une limite donc aucun intérêt (d'ailleurs tu ne devrais pas avoir deux facture avec le même id c'est une ânerie ;) ).

Sinon pour une requête il faut une sous requête corrélée dans le from mais je ne suis certain que cela soit possible.
Si tu fournit le ddl de ses tables plus un jeux de données minimal (bidon mais cohérent) je pourrais tester.

@+
Il en faut peu pour être heureux ......

Mammouth du PHP | 2278 Messages

30 nov. 2013, 12:13

Il n'y aurait pas du join dans le coin où du where quelque chose pour avoir une seule requete?
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

Petit nouveau ! | 3 Messages

30 nov. 2013, 14:21

Je suis d'accord avec le fait d'afficher les 5000 lignes ne sert a rien. Mais en gros, je récupère ces informations dans une datatable avec un champ recherche ! C'est grâce à cela qu'après j'affiche ce que je souhaite en faisant ma recherche ( ce qui réduit l'affichage entre 5 et 10 résultat).

D'ailleurs avec datatables je pagine mes pages mais la requete se réalise quand meme sur la totalité des informations de la table.

Mammouth du PHP | 2278 Messages

30 nov. 2013, 15:59

Je vais moogliser aussi:
A-t-on besoin à l'écran de la liste de tous les adhérents au même moment?
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

Mammouth du PHP | 504 Messages

30 nov. 2013, 17:21

je momoglise aussi, en plus de ce qui a été précedement dit:

a t on besoin de l'ensemble des information liés à l'adhérent ?

Une façon d'optimiser des requetes mysql: placer des idex sur les champs de recherche (champ dans la clause WHERE) et surtout ne prendre dans la base que ce qui est utile et necessaire (ex: si on a besoin que l'id, on ne fait un SELECT que sur l'id et pas les autres champs de la base).

(P.S: si tu vas chercher 5 000 données et que pour chaque tu traites encore dessus, le tout sur une page. c'est pas gagné :cry: et vu le nombre de champs à chaque fois, tu n'auras jamais une temps d'affichage satisfaisant. 1/ paginer tes résultats, 2/ selectionner que ce qui strictment neccessaire 3/ index sur les champs de recherche)

Mammouth du PHP | 571 Messages

30 nov. 2013, 17:34

ta pagination est faite côté client(js) donc n'a aucun impact sur la performance de ta requête qui doit toujours retourner 5k lignes.Or c'est au niveau du serveur mysql quil faut restreindre, avec la clause LIMIT, la plage de lignes à afficher.Par exemple, tu veux afficher 10 lignes par page:
//Pour la page 1:
$sql="SELECT a.id_adh, a.nom_adh, a.prenom_adh, a.tel_adh, a.etat_adh, f.id_fact, f.date_fact, f.duree_fact, f.montant_fact, f.id_adh_fact FROM adherents a JOIN facture f ON f.id_adh_fact = a.id_adh ORDER BY date_fact DESC LIMIT 0,10 ";

//Pour la page 2:
$sql="SELECT a.id_adh, a.nom_adh, a.prenom_adh, a.tel_adh, a.etat_adh, f.id_fact, f.date_fact, f.duree_fact, f.montant_fact, f.id_adh_fact FROM adherents a JOIN facture f ON f.id_adh_fact = a.id_adh ORDER BY date_fact DESC LIMIT 10,10 ";

//Pour la page n:
$sql="SELECT a.id_adh, a.nom_adh, a.prenom_adh, a.tel_adh, a.etat_adh, f.id_fact, f.date_fact, f.duree_fact, f.montant_fact, f.id_adh_fact FROM adherents a JOIN facture f ON f.id_adh_fact = a.id_adh ORDER BY date_fact DESC LIMIT (n-1)*10,10 ";
en complément avec tout ce qui a été dit plus haut, tu peux prévoir la mise en place d'un cache côté serveur et d'un cache client.Le cache serveur permet d'éviter de générer des pages dynamiques entre plusieurs appels à condition que ces dernières ne changent pas d'un appel à l'autre. Le cache client quant à lui permet d’éviter au serveur de générer encore une nouvelle page au prochain appel pour le même navigateur.

Mammouth du PHP | 571 Messages

30 nov. 2013, 17:40

un tuto pour sur la pagination:
pagination

Petit nouveau ! | 3 Messages

02 déc. 2013, 15:39

Merci à tous pour vos conseils ainsi que l'aide pour la requete !