Page 1 sur 1

Ouverture et fermeture sur les requetes

Posté : 24 juil. 2007, 12:35
par aelurus
Bonjour tous

Vaut il mieux faire plusieurs requêtes sql avant de fermer la connexion à la base et d'utiliser mysql_free_result() sur chaque requête ou simplement de fermer la connexion à chaque requête.
Cela bien sur but d'alléger la charge du serveur.

Merci

Posté : 24 juil. 2007, 12:49
par Hubert Roksor
Ouvrir/fermer les connexions est très coûteux, le mieux reste d'ouvrir la connexion le plus tard possible dans le script (sans toutefois aller trop loin, inutile de deviser un système super complexe pour ouvrir la connexion au tout dernier moment) et la fermer dès que tu sais que tu n'en auras plus besoin.

Utiliser mysql_free_result() en sortie de boucle est une bonne pratique. :pouce:

Posté : 24 juil. 2007, 14:47
par aelurus
Cela confirme effectivement mes doutes.
Plutôt que de pondre un système pour ouvrir ou fermer la connexion il serait surement plus judicieux de diminuer le nombre de requête que j'utilise.
Notamment sur un qui me sert a construire un menu avec trois sous niveaux de répertoires ou l'on peux y trouver des articles, donc c'est une grosse boucles de requêtes tout sa.
Merci de ta réponse

Posté : 24 juil. 2007, 14:52
par zeus
Notamment sur un qui me sert a construire un menu avec trois sous niveaux de répertoires ou l'on peux y trouver des articles, donc c'est une grosse boucles de requêtes tout sa.
Des requêtes dans une boucle, c'est souvent optimisable ;)

Il vaut souvent mieux une bonne requête bien chiadée qu'une myriade de petites requêtes dans une boucle

Posté : 24 juil. 2007, 15:06
par Hubert Roksor
Le point important étant "dans une boucle", parce que sinon il vaut souvent mieux exécuter 2 petites requêtes qu'une grosse. :)

À part ça, on peut dire que les cas qui nécessitent d'utiliser une requête dans une boucle sont, au mieux, extrêmement rares.

Posté : 24 juil. 2007, 16:21
par aelurus
Je suis persuader que mon script en question est optimisable j'en ai sué des rond de chapeau à le mettre en place puis j'ai tenter de le transformer en une seule requête via lecture d'un gros tableau ... je me suis cassé le nez dessus.

Grosso modo mon script lit deux tables une pour le menu et l'autre pour le contenu.
La structure de la table menu et je pense assez courant :

id, titre, parent, l'id est unique et s'auto incrémente chaque menu a comme parent 0 et chaque enfant et petit enfant tout comme les articles prennent comme entrée dans 'parent' l 'id' du grand frere ou du menu dont il depend.....
Ce qui donne pour chaque menu avec comme parent O on affiche (1)

ensuite je cherche les articles liées à ce menu on affiche (2)

ensuite je cherche les sous menu liées à ce menu on affiche (3)
pour chaque sous menu trouvé on cherche ces articles on affiche(4)
ensuite je cherche les sous sous menu liées à ce sous menu on affiche (5)
pour chaque sous sous menu trouvé on cherche ces articles on affiche(6)

Je ne descend pas plus bas que trois niveau un par soucis d'affichage deux parce que je n'ai pas réussi a mettre cela en récursivités ...
Donc effectivement cela devient vite une usine à requêtes. Il me semble que j'avais poster mon bout de code par ici justement pour avoir un avis dessus je vais rechercher le post.
A savoir qu'il a quand même du évoluer depuis en une boucle de fonction car bien évidement cette boucle sert dans l'affichage client tout comme dans l'affichage de l'administration de ce menu ( ouille la aussi ce fut douloureux et sa l'est encore ^^).

Voila le code qui affiche mon menu
<?
$time_start = getmicrotime();
//affichage des menus
$sql = mysql_query("SELECT id_menu, titre, ordre FROM `menu` WHERE `parent`=0 ORDER BY `ordre` ASC LIMIT 0, 6 ");

while($menu=mysql_fetch_assoc($sql))
    {
        echo"\t<ul>\r";
        echo "\t\t\t<li><a href='#' >(M)".htmlentities($menu[titre])."</a> N°($menu[ordre])\r";
        //article
        $sqlarticle = mysql_query("SELECT `id_article`,`auteur`,`date`,`texte`,`titre`,`date_maj`,`appartenance`,`ordre` FROM `article` WHERE `appartenance`='$menu[id_menu]' ORDER BY `ordre` ASC ");
        if (!mysql_numrows($sqlarticle) == 0 ) echo"\t\t\t\t<ul>\r";
        while($article=mysql_fetch_assoc($sqlarticle))
            {
                echo "\t<li><a href='#' >(A)".htmlentities($article[titre])."</a> N°($menu[ordre].$article[ordre])<br /> ";
            }
            if (!mysql_numrows($sqlarticle) == 0 ) echo"\t\t\t\t</ul> \r";
            
        $sqlsm = mysql_query("SELECT id_menu, parent, titre, ordre FROM `menu` WHERE `parent`='$menu[id_menu]' ORDER BY `ordre` ASC ");
        //sousmenu premier niveau
                if (!mysql_numrows($sqlsm) == 0 ) echo"\t\t\t\t<ul>\r";
        while($sousmenu=mysql_fetch_assoc($sqlsm))
            {
                echo "\t\t<li><a href='#'class='daddy' >(SM)".$sousmenu[titre]."</a> N°($menu[ordre].$sousmenu[ordre])\r";
                //article deuxieme niveau
                $sqlarticle1 = mysql_query("SELECT `id_article`,`auteur`,`date`,`texte`,`titre`,`date_maj`,`appartenance`,`ordre` FROM `article` WHERE `appartenance`='$sousmenu[id_menu]' ORDER BY `ordre` ASC ");
                if (!mysql_numrows($sqlarticle1) == 0 ) echo"\t\t\t<ul>\r";
                while($article1=mysql_fetch_assoc($sqlarticle1))
                    {
                        echo "\t\t\t<li><a href='#' >(A)".htmlentities($article1[titre])."</a> N°($menu[ordre].$sousmenu[ordre].$article1[ordre]) ";
                    }
                if (!mysql_numrows($sqlarticle1) == 0 ) echo"\t\t\t</ul> \r";
                //sousmenu deuxieme niveau
                $sqlssm = mysql_query("SELECT id_menu, parent, titre, ordre FROM `menu` WHERE `parent`='$sousmenu[id_menu]' ORDER BY `ordre` ASC ");
                if (!mysql_numrows($sqlssm) == 0 ) echo"\t\t\t\t<ul>\r";
                while($sous_sousmenu=mysql_fetch_assoc($sqlssm))
                    {
                        echo "<li><a href='#'class='daddy' >(SSM)".$sous_sousmenu[titre]."</a> N°($menu[ordre].$sousmenu[ordre].$sous_sousmenu[ordre])\r";
                        //article troisieme niveau
                $sqlarticle2 = mysql_query("SELECT `id_article`,`auteur`,`date`,`texte`,`titre`,`date_maj`,`appartenance`,`ordre` FROM `article` WHERE `appartenance`='$sous_sousmenu[id_menu]' ORDER BY `ordre` ASC ");
                if (!mysql_numrows($sqlarticle2) == 0 ) echo"\t<ul>\r";
                while($article2=mysql_fetch_assoc($sqlarticle2))
                    {
                        echo "<li><a href='#' >(A)".htmlentities($article2[titre])."</a> N°($menu[ordre].$sous_sousmenumenu[ordre].$article2[ordre]) ";
                    }
                if (!mysql_numrows($sqlarticle2) == 0 ) echo"</ul>\r";    
                
                    }
                if (!mysql_numrows($sqlssm) == 0 ) echo"</ul>\r";
                
            }
            if (!mysql_numrows($sqlsm) == 0 ) echo"\t\t\t\t</ul>\r";
        echo"</ul>\r";    
    }
$time_end = getmicrotime();
$time = substr(($time_end - $time_start),0,9);
$message.="<p class='tempgene'>Script droit générée en ".$time." s</p>";

?> 
De mémoire je crois que je tournais dans les 1,6 segondes mais je dois vérifier la chose....

Posté : 24 juil. 2007, 17:00
par Genova
Oui effectivement ton script est vraiment crade en terme d'optimisation.

Déjà première chose : vérifie les retours d'erreurs de mysql_query()
mysql_query($sql) OR die(mysql_error());
le jour ou tu auras une erreur tu sauras d'où elle vient.

Ensuite en terme d'optimisation, tu fais des requêtes en boucle, et c'est mal. Dit toi que tu aurais pu gérer tout ton arbre en une seule requête en suivant certains shémas, par exemple : http://sqlpro.developpez.com/cours/arborescence/

Dans ton cas voilà un moyen simple de tout récupérer en une requête :
$sql = 'SELECT id_menu, titre, ordre, parent
		FROM menu 
		ORDER BY ordre ASC';
$result = mysql_query($sql) OR die(mysql_error());
$rows = array();
while ($row = mysql_fetch_assoc($result))
{
	$rows[] = $row;
}
mysql_free_result($result);

$tree = array();
fill_tree($tree, $rows);

echo '<pre>';
print_r($tree);
echo '</pre>';

function fill_tree(&$tree, $rows, $parent = 0)
{
	foreach ($rows AS $row)
	{
		if ($row['parent'] == $parent)
		{
			$tree[$row['id_menu']] = $row;
			$tree[$row['id_menu']]['childs'] = array();
			fill_tree($tree[$row['id_menu']]['childs'], $store, $row['id_menu']);
		}
	}
}
$tree contiendra ton menu, organisé comme un arbre (avec les enfants, les enfants des enfants, etc ...), il te suffit d'un foreach () pour le parcourir et afficher tout ça proprement ;)

Posté : 25 juil. 2007, 10:00
par aelurus
Grand merci à toi Genova pour le lien très instructif et pour ce script qui je pense vas m'être d'une grande utilité. Je vois a transformer mon script de requête en un foreach. Je suis curieux de voir la différence d'exécution qui ressortira de tout sa.