<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>php-experts.org - développement php et internet &#187; sql</title>
	<atom:link href="http://www.php-experts.org/tag/sql/feed" rel="self" type="application/rss+xml" />
	<link>http://www.php-experts.org</link>
	<description>Ressources sur le développement internet, PHP/MySQL, Ajax, marketing online, référencement...</description>
	<lastBuildDate>Sun, 27 Jun 2010 23:09:22 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Optimisation d&#8217;une requête SQL avec EXPLAIN et log_slow_queries</title>
		<link>http://www.php-experts.org/bases-de-donnees/mysql/autopsie-et-optimisation-dune-requete-sql-avec-explain-et-log_slow_queries-14</link>
		<comments>http://www.php-experts.org/bases-de-donnees/mysql/autopsie-et-optimisation-dune-requete-sql-avec-explain-et-log_slow_queries-14#comments</comments>
		<pubDate>Sat, 12 Jul 2008 17:22:34 +0000</pubDate>
		<dc:creator>Didier</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[explain]]></category>
		<category><![CDATA[log_slow_queries]]></category>
		<category><![CDATA[long_query_time]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://www.php-experts.org/?p=14</guid>
		<description><![CDATA[Depuis quelques temps, un serveur qui héberge quelques petits sites s&#8217;est mis à monter régulièrement en charge, sans augmentation de trafic, ni changements applicatifs. J&#8217;ai laissé traîner les choses, ne sachant pas d&#8217;où venait le souci.
Il aura fallu cinq minutes de travail et l&#8217;utilisation de la commande shell top, de la directive de configuration MySQL [...]]]></description>
			<content:encoded><![CDATA[<p>Depuis quelques temps, un serveur qui héberge quelques petits sites s&#8217;est mis à monter régulièrement en charge, sans augmentation de trafic, ni changements applicatifs. J&#8217;ai laissé traîner les choses, ne sachant pas d&#8217;où venait le souci.<br />
Il aura fallu cinq minutes de travail et l&#8217;utilisation de la commande shell <strong>top</strong>, de la directive de configuration MySQL <strong>log_slow_queries</strong> et de la commande SQL <strong>EXPLAIN</strong> pour régler le problème de lenteur des sites.<br />
<span id="more-14"></span>Tout d&#8217;abord, un <em>top</em> a confirmé mes craintes : c&#8217;est bien le serveur MySQL qui était en cause, prenait beaucoup de mémoire RAM et de ressources processeur. Il y avait donc des <strong>requêtes SQL</strong> qui avaient besoin d&#8217;être optimisées.</p>
<p>J&#8217;ai édité le fichier de configuration de MySQL (/etc/mysql/my.cnf sous Linux Debian) pour y activer l&#8217;option <strong>log-slow-queries</strong> en modifiant les trois lignes suivantes :</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">log_slow_queries = /var/log/mysql/mysql-slow.log</div>
</li>
<li class="li1">
<div class="de1">long_query_time = <span class="nu0">2</span></div>
</li>
<li class="li1">
<div class="de1">log-queries-not-using-indexes</div>
</li>
</ol>
</div>
<p>Je le répète, <strong>long_query_time = 2</strong> signifie qu&#8217;on doit logger toutes les requêtes qui mettent plus de deux secondes à s&#8217;exécuter. Après un redémarrage du serveur (cette option ne peut malheureusement pas être changée à chaud), j&#8217;ai attendu la montée en charge suivante pour que MySQL (grâce à long_query_time) enregistre sagement toutes les requêtes mettant plus de 2 secondes à s&#8217;exécuter (log_query_time est exprimé en secondes et doit être un nombre entier compris entre 1 et 10), et celles qui n&#8217;utilisaient aucun index, dans le fichier /var/log/mysql-slow.log</p>
<p>Voici ce que j&#8217;y ai trouvé :</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"># Query_time: 0 &nbsp;Lock_time: 0 &nbsp;Rows_sent: 5 &nbsp;Rows_examined: 17165
</div>
</li>
<li class="li1">
<div class="de1">SELECT * FROM chanson LEFT JOIN artiste ON artiste_ID = ID_artiste WHERE artiste_ID = 50 ORDER BY RAND() LIMIT 5;</div>
</li>
</ol>
</div>
<p>Quasiment 20.000 lignes examinées (la totalité de la table) pour une requête qui en ramènera seulement 5, c&#8217;est beaucoup.</p>
<p>Je me suis connecté à <strong>phpMyAdmin</strong>, et j&#8217;ai utilisé la commande <strong>explain</strong>, en rajoutant simplement le mot <strong>EXPLAIN</strong> devant ma requête SQL :</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">EXPLAIN</span> <span class="kw1">SELECT</span> *</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">FROM</span> chanson</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">LEFT</span> <span class="kw1">JOIN</span> artiste <span class="kw1">ON</span> artiste_ID = ID_artiste</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">WHERE</span> artiste_ID = <span class="nu0">50</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">ORDER</span> <span class="kw1">BY</span> RAND<span class="br0">&#40;</span> <span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">LIMIT</span> <span class="nu0">5</span>;</div>
</li>
</ol>
</div>
<p>La commande MySQL EXPLAIN permet de voir, notamment, les clés (index, primary, uniques&#8230;) utilisées pour aller chercher les résultats d&#8217;une requête, ainsi que le nombre de lignes parcourues.<br />
Voici quel a été le résultat de la commande Explain :<br />
<img class="alignnone size-medium wp-image-15" title="MySQL Explain" src="http://www.php-experts.org/wp-content/uploads/2008/07/explain.png" alt="MySQL Explain" width="560" height="50" /></p>
<p>J&#8217;ai ajouté un &#8220;ID_artiste = 50&#8243; dans la <strong>clause WHERE</strong>, qui n&#8217;a rien changé. Explain renvoyait toujours &#8220;NULL&#8221; dans les Possible keys concernant la table Chanson. Après vérification, en effet, il n&#8217;y avait aucun index sur ce champ de la table, pourtant souvent utilisé dans mes clauses WHERE. Un <em>ALTER TABLE `chanson` ADD INDEX(`artiste_ID`)</em> plus tard, la création de l&#8217;index sur le champ de la base de données concernée a permis de changer le résultat de l&#8217;EXPLAIN sur la même requête SQL :<br />
<img class="alignnone size-medium wp-image-16" title="MySQL Explain 2" src="http://www.php-experts.org/wp-content/uploads/2008/07/explain2.png" alt="MySQL Explain" width="560" height="50" /><br />
Plus que 76 lignes lues pour renvoyer la réponse, la requête n&#8217;apparaitra très certainement plus dans le <strong>slow_query_log</strong>.</p>
<p>En recommençant l&#8217;opération (toujours avec Explain) sur toutes les requêtes qui se trouvaient dans le fichier de log, j&#8217;ai trouvé plusieurs points à améliorer pour <strong>accroître les performances du serveur MySQL</strong>. Finis, les problèmes de montée en charge !</p>
<p>Pour en savoir plus :<br />
Documentation officielle MySQL de la <a href="http://dev.mysql.com/doc/refman/5.0/fr/explain.html">syntaxe de EXPLAIN</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.php-experts.org/bases-de-donnees/mysql/autopsie-et-optimisation-dune-requete-sql-avec-explain-et-log_slow_queries-14/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
