<?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>dbnewz &#187; 5.0</title>
	<atom:link href="http://www.dbnewz.com/category/mysql/50/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dbnewz.com</link>
	<description>le blog français sur les SGBD - MySQL, Oracle et plus...</description>
	<lastBuildDate>Wed, 28 Jul 2010 14:01:15 +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>Encore un nouveau livre sur MySQL !</title>
		<link>http://www.dbnewz.com/2010/06/18/encore-un-nouveau-livre-sur-mysql/</link>
		<comments>http://www.dbnewz.com/2010/06/18/encore-un-nouveau-livre-sur-mysql/#comments</comments>
		<pubDate>Fri, 18 Jun 2010 14:18:57 +0000</pubDate>
		<dc:creator>stephane</dc:creator>
				<category><![CDATA[5.0]]></category>
		<category><![CDATA[5.1]]></category>
		<category><![CDATA[DBNewz]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[livres]]></category>

		<guid isPermaLink="false">http://www.dbnewz.com/?p=597</guid>
		<description><![CDATA[Après l&#8217;excellent &#171;&#160;MySQL5, Audit et optimisation&#160;&#187; sorti fin mars, voici un nouveau livre pour vous occuper sur la plage cet été : MySQL5, Administration et optimisation.
Pour vous mettre l&#8217;eau à la bouche, la TDM_MySQL5_Admin_Optim et un Extrait_MySQL5_Admin_Optim consacré aux verrous et transactions sont disponibles
Le livre est bien sûr disponible dans toutes les bonnes librairies informatiques [...]]]></description>
			<content:encoded><![CDATA[<p>Après l&#8217;excellent &laquo;&nbsp;MySQL5, Audit et optimisation&nbsp;&raquo; sorti fin mars, voici un nouveau livre pour vous occuper sur la plage cet été : <a href="http://www.editions-eni.fr/Livres/MySQL-5-administration-et-optimisation/.5_3a6222cf-b921-41f5-886c-c989f77ba994_cb487b7e-d258-456f-9051-6cc0e5e2b22f_817f0d89-4a9c-49f7-ad91-63e24f3c9941_1_0_d9bd8b5e-f324-473f-b1fc-b41b421c950f.html">MySQL5, Administration et optimisation</a>.<br />
Pour vous mettre l&#8217;eau à la bouche, la <a href='http://www.dbnewz.com/wp-content/uploads/2010/06/TDM_MySQL5_Admin_Optim.pdf'>TDM_MySQL5_Admin_Optim</a> et un <a href='http://www.dbnewz.com/wp-content/uploads/2010/06/Extrait_MySQL5_Admin_Optim.pdf'>Extrait_MySQL5_Admin_Optim</a> consacré aux verrous et transactions sont disponibles</p>
<p>Le livre est bien sûr disponible dans toutes les bonnes librairies informatiques et autres FNAC, Amazon &#8230;</p>
<p>Bonne lecture !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dbnewz.com/2010/06/18/encore-un-nouveau-livre-sur-mysql/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Trois pdf de &#171;&#160;MySQL 5, Audit et optimisation&#160;&#187; à télécharger</title>
		<link>http://www.dbnewz.com/2010/03/24/trois-pdf-de-mysql-5-audit-et-optimisation-a-telecharger/</link>
		<comments>http://www.dbnewz.com/2010/03/24/trois-pdf-de-mysql-5-audit-et-optimisation-a-telecharger/#comments</comments>
		<pubDate>Wed, 24 Mar 2010 17:02:48 +0000</pubDate>
		<dc:creator>arnaud</dc:creator>
				<category><![CDATA[5.0]]></category>
		<category><![CDATA[DBNewz]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://www.dbnewz.com/?p=521</guid>
		<description><![CDATA[Comme promis, voici quelques fichiers pdf du livre &#171;&#160;MySQL 5, Audit et optimisation&#160;&#187;.
Vous trouverez ici-même le sommaire et l&#8217;avant-propos. Le premier chapitre (&#171;&#160;Gérer une situation d&#8217;urgence avec MySQL&#160;&#187;), est disponible sur le blog d&#8217;Olivier.
Le livre sort ce jeudi en librairie, fnac.com, eyrolles.com, amazon.fr&#8230;
Bonne lecture !
]]></description>
			<content:encoded><![CDATA[<p>Comme <a href="http://www.dbnewz.com/2010/03/23/sortie-imminente-de-mysql-5-audit-et-optimisation/" target="_blank">promis</a>, voici quelques fichiers pdf du livre &laquo;&nbsp;MySQL 5, Audit et optimisation&nbsp;&raquo;.</p>
<p>Vous trouverez ici-même le <a href="http://www.dbnewz.com/wp-content/uploads/2010/03/tdm_mysql5_audit_optimisation.pdf">sommaire </a>et <a href="http://www.dbnewz.com/wp-content/uploads/2010/03/avant_propos_mysql5_audit_optimisation.pdf">l&#8217;avant-propos</a>. Le <a href="http://dasini.net/blog/2010/03/24/extraits-du-livre-audit-et-optimisation-%E2%80%93-mysql-5/" target="_blank">premier chapitre</a> (&laquo;&nbsp;Gérer une situation d&#8217;urgence avec MySQL&nbsp;&raquo;), est disponible sur le blog d&#8217;Olivier.</p>
<p>Le livre sort ce jeudi en librairie, <a href="http://livre.fnac.com/a2766870/Pascal-Borghino-Audit-et-optimisation-MySQL-5" target="_blank">fnac.com</a>, <a href="http://www.eyrolles.com/Informatique/Livre/audit-et-optimisation-mysql-5-9782212126341" target="_blank">eyrolles.com</a>, <a href="http://www.amazon.fr/Audit-optimisation-MySQL-pratiques-ladministrateur/dp/2212126344/" target="_blank">amazon.fr</a>&#8230;</p>
<p>Bonne lecture !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dbnewz.com/2010/03/24/trois-pdf-de-mysql-5-audit-et-optimisation-a-telecharger/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Sortie imminente de &#171;&#160;MySQL 5, Audit et optimisation&#160;&#187;</title>
		<link>http://www.dbnewz.com/2010/03/23/sortie-imminente-de-mysql-5-audit-et-optimisation/</link>
		<comments>http://www.dbnewz.com/2010/03/23/sortie-imminente-de-mysql-5-audit-et-optimisation/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 22:09:55 +0000</pubDate>
		<dc:creator>arnaud</dc:creator>
				<category><![CDATA[5.0]]></category>
		<category><![CDATA[DBNewz]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://www.dbnewz.com/?p=508</guid>
		<description><![CDATA[Vous l&#8217;avez remarqué, depuis quelques mois dbnewz n&#8217;est plus aussi régulièrement mis à jour. A qui la faute ? Probablement à l&#8217;ouvrage que nous (Pascal Borghino, Olivier Dasini, Arnaud Gadal) avons rédigé récemment. La charge de travail nécessaire à la rédaction de &#171;&#160;MySQL 5, audit et optimisation&#160;&#187;, un ouvrage rédigé en plus de nos activités [...]]]></description>
			<content:encoded><![CDATA[<p>Vous l&#8217;avez remarqué, depuis quelques mois dbnewz n&#8217;est plus aussi régulièrement mis à jour. A qui la faute ? Probablement à l&#8217;ouvrage que nous (Pascal Borghino, <a href="http://dasini.net/blog/" target="_blank">Olivier Dasini</a>, Arnaud Gadal) avons rédigé récemment. La charge de travail nécessaire à la rédaction de &laquo;&nbsp;MySQL 5, audit et optimisation&nbsp;&raquo;, un ouvrage rédigé en plus de nos activités professionnelles, a temporairement pris le dessus sur le temps que nous consacrions habituellement au blog.</p>
<div id="attachment_512" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.dbnewz.com/wp-content/uploads/2010/03/couv_audit_optimisation_mysql5.png" target="_blank"><img class="size-medium wp-image-512" title="couv_audit_optimisation_mysql5" src="http://www.dbnewz.com/wp-content/uploads/2010/03/couv_audit_optimisation_mysql5-300x178.png" alt="" width="300" height="178" /></a><p class="wp-caption-text">MySQL 5 Audit et optimisation</p></div>
<p>La rédaction de l&#8217;ouvrage étant maintenant dernière nous, les billets vont pouvoir reprendre à une allure plus digne de ce blog ! Je tiens d&#8217;ailleurs à remercier Stéphane qui a enrichi le site pendant que Pascal et moi étions à 100% sur le livre : l&#8217;intérêt de blogger en équipe&#8230; <img src='http://www.dbnewz.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>La date officielle de sortie est le 25 mars. D&#8217;ici là <a href="http://www.dbnewz.com/wp-content/uploads/2010/03/MySQL5_audit_optimisation.pdf">voici le pdf</a> du communiqué de presse concernant l&#8217;ouvrage. Celui-ci était présent en quantité limitée lors du dernier salon Solutions Linux.</p>
<p>Il est d&#8217;ores et déjà disponible en <a href="http://livre.fnac.com/a2766870/Pascal-Borghino-Audit-et-optimisation-MySQL-5" target="_blank">précommande</a>.</p>
<p>Nous posterons ici même d&#8217;ici peu quelques morceaux choisis en pdf issus du livre dès que nous les aurons reçus de notre éditeur, c&#8217;est imminent.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dbnewz.com/2010/03/23/sortie-imminente-de-mysql-5-audit-et-optimisation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>le trigger au secours des function-based index (FBI)</title>
		<link>http://www.dbnewz.com/2009/04/01/le-trigger-au-secours-des-function-based-index-fbi/</link>
		<comments>http://www.dbnewz.com/2009/04/01/le-trigger-au-secours-des-function-based-index-fbi/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 06:36:55 +0000</pubDate>
		<dc:creator>arnaud</dc:creator>
				<category><![CDATA[5.0]]></category>
		<category><![CDATA[5.1]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[index]]></category>
		<category><![CDATA[pratique]]></category>

		<guid isPermaLink="false">http://www.dbnewz.com/?p=228</guid>
		<description><![CDATA[Constat : les FBI (function-based index) ne sont pas disponibles en MySQL.
Comment faire dans ce cas pour obtenir par exemple l&#8217;équivalent de l&#8217;index suivant ?
CREATE INDEX idx_str_len ON my_table (length(str));
Une des solutions les plus simples consiste à utiliser un trigger qui assurera la mise à jour d&#8217;une colonne supplémentaire que l&#8217;on créera dans la table [...]]]></description>
			<content:encoded><![CDATA[<p>Constat : les FBI (function-based index) ne sont pas disponibles en MySQL.</p>
<p>Comment faire dans ce cas pour obtenir par exemple l&#8217;équivalent de l&#8217;index suivant ?</p>
<p><code>CREATE INDEX idx_str_len ON my_table (<strong>length</strong>(str));</code></p>
<p>Une des solutions les plus simples consiste à utiliser un <a href="http://dev.mysql.com/doc/refman/5.1/en/create-trigger.html" target="_blank">trigger</a> qui assurera la mise à jour d&#8217;une colonne supplémentaire que l&#8217;on créera dans la table cible.</p>
<p>Partons de la table suivante :</p>
<p><code>CREATE TABLE `t` (<br />
`id` mediumint(8) unsigned NOT NULL auto_increment,<br />
`date` timestamp NOT NULL,<br />
`str` varchar(100) NOT NULL default '0',<br />
PRIMARY KEY  (`id`)<br />
) ENGINE=MyISAM;</code></p>
<p>Le but est de pouvoir obtenir une réponse rapide à la requête suivante :</p>
<p>select sql_no_cache count(*) from t where length(str) between 20 and 70;</p>
<p>Afin de simuler un jeu d&#8217;essai similaire à ma table de production, j&#8217;alimente ma table de test grâce à <a href="http://www.dbnewz.com/2008/08/19/generer-un-jeu-de-donnees-shell-mysqlslap-et-procedure-stockee/" target="_blank">une procédure stockée</a> déjà évoquée sur dbnewz.</p>
<p>Je la modifie ici afin d&#8217;obtenir une longueur aléatoire pour ma chaîne de caractère &laquo;&nbsp;str&nbsp;&raquo; :</p>
<p><code>delimiter //<br />
CREATE PROCEDURE fill_table(nb_rows INT)<br />
BEGIN<br />
DECLARE i INT DEFAULT 0;<br />
REPEAT<br />
SET i = i + 1;<br />
INSERT INTO t (str) VALUES(repeat('a', round(rand()*100)));<br />
UNTIL i &gt;= nb_rows<br />
END REPEAT;<br />
END;<br />
//<br />
delimiter ;</code></p>
<p>Afin de valider deux scénarios pour ce billet, j&#8217;ai utilisé deux machines, une machine perso et un serveur pro. Deux configurations différentes : la perso n&#8217;est absolument pas &laquo;&nbsp;tunée&nbsp;&raquo;, en configuration strictement d&#8217;origine (5.1.32), la seconde a des processeurs et de la RAM à revendre.<br />
J&#8217;afficherai donc les temps d&#8217;exécution des deux machines à titre de comparaison.</p>
<p><span id="more-228"></span>Pour renseigner ma table de test à hauteur de 2 millions d&#8217;enregistrements, j&#8217;appelle ma procédure stockée :</p>
<p>Perso :<br />
mysql&gt; call fill_table(2000000);<br />
Query OK, 1 row affected (1 min 52.97 sec)</p>
<p>Pro :<br />
mysql&gt; call fill_table(2000000);<br />
Query OK, 1 row affected (42.23 sec)</p>
<p>Je souhaite tester ma requête sous InnoDB, je modifie le moteur de la table :</p>
<p>mysql&gt; alter table t engine=&#8217;innodb&#8217;;<br />
Query OK, 2000000 rows affected (43.57 sec)<br />
Records: 2000000  Duplicates: 0  Warnings: 0</p>
<p>mysql&gt; alter table t engine=&#8217;innodb&#8217;;<br />
Query OK, 2000000 rows affected (13.10 sec)<br />
Records: 2000000  Duplicates: 0  Warnings: 0</p>
<p>J&#8217;ai testé pour vous : il est <strong>bien plus rapide</strong> d&#8217;insérer en MyISAM et de faire l&#8217;ALTER en InnoDB que d&#8217;insérer directement en InnoDB :</p>
<p>Test de chargement avec <strong>table en InnoDB</strong> <strong>d&#8217;origine</strong> sur la machine <strong>perso</strong> :<br />
mysql&gt; call fill_table(<strong>100000</strong>);<br />
Query OK, 1 row affected (1 min 14.15 sec)</p>
<p>=&gt; Déjà 30 secondes de plus (70% plus lent) pour 20x moins de données !</p>
<p>La machine pro (en 5.0.56) est bien plus rapide mais valide elle aussi la stratégie de passer par MyISAM en premier lieu :<br />
Chargement d&#8217;une <strong>table en InnoDB</strong> sur serveur <strong>pro</strong> :<br />
mysql&gt; call fill_table(2000000);<br />
Query OK, 1 row affected (1 min 11.16 sec)</p>
<p>=&gt; A comparer avec les 42 sec (chargement MyISAM natif) + 13 sec (alter InnoDB) = 55 s. Au moins 30% plus rapide.</p>
<p>On obtient une table contenant des enregistrements du type :</p>
<p>mysql&gt; select * from t limit 5;<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
| id | date                | str<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
|  1 | 2009-03-30 22:18:02 | aaaaaaaa<br />
|  2 | 2009-03-30 22:18:02 | aaaaaaaaaaaaaaaa<br />
|  3 | 2009-03-30 22:18:02 | aaaaaaaaaaaaaaaaaaaaaaa<br />
|  4 | 2009-03-30 22:18:02 | aaaaaaaaaaa<br />
|  5 | 2009-03-30 22:18:02 | aaa<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Nous voici donc avec un jeu d&#8217;essai raisonnable, prêt à en découdre avec cette requête&#8230;</p>
<p>mysql&gt; explain select sql_no_cache count(*) from t where length(str) between 20 and 70;</p>
<p>*************************** 1. row ***************************<br />
id: 1<br />
select_type: SIMPLE<br />
table: t<br />
type: ALL<br />
possible_keys: NULL<br />
key: NULL<br />
key_len: NULL<br />
ref: NULL<br />
rows: 2015427<br />
Extra: Using where<br />
1 row in set (0.00 sec)</p>
<p>&#8230; Au temps d&#8217;exécution pitoyable. Sur la machine perso, j&#8217;obtiens en moyenne :</p>
<p>mysql&gt; select sql_no_cache count(*) from t where length(str) between 20 and 70;<br />
+&#8212;&#8212;&#8212;-+<br />
| count(*) |<br />
+&#8212;&#8212;&#8212;-+<br />
|  1019970 |<br />
+&#8212;&#8212;&#8212;-+<br />
1 row in set (1.83 sec)</p>
<p>Sur le serveur pro :</p>
<p>mysql&gt; select sql_no_cache count(*) from t where length(str) between 20 and 70;<br />
+&#8212;&#8212;&#8212;-+<br />
| count(*) |<br />
+&#8212;&#8212;&#8212;-+<br />
|  1020008 |<br />
+&#8212;&#8212;&#8212;-+<br />
1 row in set (0.82 sec)</p>
<p>L&#8217;innodb_buffer_pool_size de la machine perso est complètement sous-dimensionné pour contenir toutes les données de ma table. L&#8217;intérêt ici est de tester ce qui se passe quand les données ne sont pas montées en RAM (comportement de MyISAM qui charge les datas dans le cache OS).</p>
<p>Constatons les &laquo;&nbsp;dégats&nbsp;&raquo; sur la machine perso :</p>
<p>mysql&gt; show variables like &#8216;innodb_buffer_pool_size&#8217;;<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;+<br />
| Variable_name           | Value   |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;+<br />
| innodb_buffer_pool_size | 8 388 608<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;+</p>
<p>&#8230; le jour et la nuit avec :</p>
<p>mysql&gt; show variables like &#8216;innodb_buffer_pool_size&#8217;;<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;+<br />
| Variable_name           | Value      |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;+<br />
| innodb_buffer_pool_size | 3 984 588 800<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;+</p>
<p>Voyons si un index peut changer la donne ? Plaçons-le sur la colonne &laquo;&nbsp;str&nbsp;&raquo; :</p>
<p>mysql&gt; create index idx_str on t (str);<br />
Query OK, 2000000 rows affected (1 min 1.95 sec)<br />
Records: 2000000  Duplicates: 0  Warnings: 0</p>
<p>mysql&gt; create index idx_str on t (str);<br />
Query OK, 2000000 rows affected (24.95 sec)<br />
Records: 2000000  Duplicates: 0  Warnings: 0</p>
<p>Le nouveau plan d&#8217;exécution est le suivant :</p>
<p>mysql&gt; explain select sql_no_cache count(*) from t where length(str) between 20 and 70;<br />
*************************** 1. row ***************************<br />
id: 1<br />
select_type: SIMPLE<br />
table: t<br />
type: index<br />
possible_keys: NULL<br />
key: idx_str<br />
key_len: 102<br />
ref: NULL<br />
rows: 1957767<br />
Extra: Using where; Using index<br />
1 row in set (0.00 sec)</p>
<p>Nous sommes dans le cas d&#8217;un <a href="http://www.dbnewz.com/2008/11/20/les-covering-index-de-la-theorie-a-la-pratique-avec-myisam-et-innodb/" target="_blank">covering index</a> mais celui-ci n&#8217;est pas hélas pas d&#8217;une grande utilité sur la machine perso :</p>
<p>mysql&gt; select sql_no_cache count(*) from t where length(str) between 20 and 70;<br />
+&#8212;&#8212;&#8212;-+<br />
| count(*) |<br />
+&#8212;&#8212;&#8212;-+<br />
|  1019970 |<br />
+&#8212;&#8212;&#8212;-+<br />
1 row in set (1.98 sec)</p>
<p>On frôle les 2 secondes.</p>
<p>Sur la machine de prod c&#8217;est en revanche légèrement plus rapide :</p>
<p>mysql&gt; select sql_no_cache count(*) from t where length(str) between 20 and 70;<br />
+&#8212;&#8212;&#8212;-+<br />
| count(*) |<br />
+&#8212;&#8212;&#8212;-+<br />
|  1020008 |<br />
+&#8212;&#8212;&#8212;-+<br />
1 row in set (0.73 sec)</p>
<p>Stratégie : rajouter une colonne &laquo;&nbsp;str_nb&nbsp;&raquo; à ma table t et mettre à jour cette colonne selon la longueur de &laquo;&nbsp;str&nbsp;&raquo;.</p>
<p><strong>Machine Perso :</strong><br />
mysql&gt; ALTER table t ADD str_nb tinyint unsigned, ADD index idx_str_nb(str_nb);<br />
Query OK, 2000000 rows affected (1 min 9.22 sec)<br />
Records: 2000000  Duplicates: 0  Warnings: 0</p>
<p>mysql&gt; UPDATE t SET str_nb = length(str);<br />
Query OK, 2000000 rows affected (2 min 3.97 sec)<br />
Rows matched: 2000000  Changed: 2000000  Warnings: 0</p>
<p><strong>Serveur Pro :</strong><br />
mysql&gt; ALTER table t ADD str_nb tinyint unsigned, ADD index idx_str_nb(str_nb);<br />
Query OK, 2000000 rows affected (30.91 sec)<br />
Records: 2000000  Duplicates: 0  Warnings: 0</p>
<p>mysql&gt; UPDATE t SET str_nb = length(str);</p>
<p>Query OK, 2000000 rows affected (1 min 22.54 sec)<br />
Rows matched: 2000000  Changed: 2000000  Warnings: 0</p>
<p>mysql&gt; explain select sql_no_cache count(*) from t where str_nb between 20 and 70\G</p>
<p>*************************** 1. row ***************************<br />
id: 1<br />
select_type: SIMPLE<br />
table: t<br />
type: range<br />
possible_keys: idx_str_nb<br />
key: idx_str_nb<br />
key_len: 2<br />
ref: NULL<br />
rows: 914077<br />
Extra: Using where; Using index<br />
1 row in set (0.00 sec)</p>
<p>Notre requête modifiée tire parti du nouvel index :</p>
<p>mysql&gt; select sql_no_cache count(*) from t where str_nb between 20 and 70;<br />
+&#8212;&#8212;&#8212;-+<br />
| count(*) |<br />
+&#8212;&#8212;&#8212;-+<br />
|  1019970 |<br />
+&#8212;&#8212;&#8212;-+<br />
1 row in set (0.99 sec)</p>
<p>Sur la machine de prod :</p>
<p>mysql&gt; select sql_no_cache count(*) from t where str_nb between 20 and 70;<br />
+&#8212;&#8212;&#8212;-+<br />
| count(*) |<br />
+&#8212;&#8212;&#8212;-+<br />
|  1020008 |<br />
+&#8212;&#8212;&#8212;-+<br />
1 row in set (0.37 sec)</p>
<p>Résultat de ces tests : tirer parti d&#8217;une colonne &laquo;&nbsp;précalculée&nbsp;&raquo; permet de <strong>diviser par deux</strong> le temps d&#8217;exécution sur les deux machines.</p>
<p>Comment maintenir à jour cette colonne ?</p>
<p>C&#8217;est là que les <strong>triggers</strong> rentrent en jeu, on en crée deux :</p>
<p>Le premier concerne les <strong>INSERT</strong>&#8230;</p>
<p><code>DELIMITER |<br />
CREATE TRIGGER maj_str_nb_ins BEFORE INSERT ON t<br />
FOR EACH ROW BEGIN<br />
SET NEW.str_nb = length(NEW.str);<br />
END;<br />
|<br />
DELIMITER ;</code></p>
<p>&#8230; Et le second les <strong>UPDATE</strong> :</p>
<p><code>DELIMITER |<br />
CREATE TRIGGER maj_str_nb_upd BEFORE UPDATE ON t<br />
FOR EACH ROW BEGIN<br />
SET NEW.str_nb = length(NEW.str);<br />
END;<br />
|<br />
DELIMITER ;</code></p>
<p>Le mot clé &laquo;&nbsp;NEW&nbsp;&raquo; permet de faire référence à la nouvelle donnée qui est insérée. Dans le cadre d&#8217;un UPDATE il existe également le mot clé &laquo;&nbsp;OLD&nbsp;&raquo; qui permet de manipuler l&#8217;ancienne donnée, celle qui va être mise à jour.</p>
<p>Une fois insérés, ces triggers s&#8217;occuperont pour nous de mettre à jour automatiquement la colonne &laquo;&nbsp;str_nb&nbsp;&raquo;. Quelques exemples :</p>
<p>mysql&gt; insert into t (str) values (&#8216;dbnewz&#8217;);<br />
Query OK, 1 row affected (0.45 sec)</p>
<p>mysql&gt; select * from t where id = 2000001;<br />
+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+<br />
| id      | date                | str    | <strong>str_nb</strong> |<br />
+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+<br />
| 2000001 | 2009-04-01 00:35:58 | dbnewz |      <strong>6</strong> |<br />
+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+</p>
<p>mysql&gt; update t set date = &#8216;2009-04-01 03:33:33&#8242; where id = 2000001;<br />
Query OK, 1 row affected (0.35 sec)<br />
Rows matched: 1  Changed: 1  Warnings: 0</p>
<p>mysql&gt; select * from t where id = 2000001;<br />
+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+<br />
| id      | date                | str    | str_nb |<br />
+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+<br />
| 2000001 | 2009-04-01 03:33:33 | dbnewz |      6 |<br />
+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+<br />
1 row in set (0.00 sec)</p>
<p>mysql&gt; update t set str = &#8216;MySQL&#8217; where id = 2000001;<br />
Query OK, 1 row affected (0.00 sec)<br />
Rows matched: 1  Changed: 1  Warnings: 0</p>
<p>mysql&gt; select * from t where id = 2000001;<br />
+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;-+&#8212;&#8212;&#8211;+<br />
| id      | date                | str   | str_nb |<br />
+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;-+&#8212;&#8212;&#8211;+<br />
| 2000001 | 2009-04-01 00:38:18 | MySQL |      5 |<br />
+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;-+&#8212;&#8212;&#8211;+<br />
1 row in set (0.00 sec)</p>
<p>A vous de tester si ces triggers peuvent correspondre à un cas que vous cherchez à résoudre, dans ce cas précis, ils fonctionnent.</p>
<p>Merci à <a href="http://www.cybersite.com.au/blog" target="_blank">Jonathon Coombes</a> avec qui j&#8217;ai échangé autour de ce sujet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dbnewz.com/2009/04/01/le-trigger-au-secours-des-function-based-index-fbi/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>15 secondes pour installer une réplication MySQL avec MySQL Sandbox, pari tenu ?</title>
		<link>http://www.dbnewz.com/2008/10/10/15-secondes-pour-installer-une-replication-mysql-avec-mysql-sandbox-pari-tenu/</link>
		<comments>http://www.dbnewz.com/2008/10/10/15-secondes-pour-installer-une-replication-mysql-avec-mysql-sandbox-pari-tenu/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 07:08:28 +0000</pubDate>
		<dc:creator>arnaud</dc:creator>
				<category><![CDATA[4.0]]></category>
		<category><![CDATA[4.1]]></category>
		<category><![CDATA[5.0]]></category>
		<category><![CDATA[5.1]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[réplication]]></category>
		<category><![CDATA[outils]]></category>

		<guid isPermaLink="false">http://www.dbnewz.com/?p=75</guid>
		<description><![CDATA[&#171;&#160;Installez-moi une configuration MySQL composée d&#8217;un master et deux slaves, vous avez 15 secondes. Top chrono&#160;&#187;&#8230;
Non, ça n&#8217;est pas la dernière énigme à la mode pour rentrer chez Google mais plutôt une question qui pourrait devenir presque banale pour un entretien d&#8217;embauche pour un DBA MySQL à l&#8217;avenir, qui sait ?
Face à un tel défi, [...]]]></description>
			<content:encoded><![CDATA[<p>&laquo;&nbsp;Installez-moi une configuration MySQL composée d&#8217;un master et deux slaves, vous avez 15 secondes. Top chrono&nbsp;&raquo;&#8230;</p>
<p>Non, ça n&#8217;est pas la dernière énigme à la mode pour rentrer chez Google mais plutôt une question qui pourrait devenir presque banale pour un entretien d&#8217;embauche pour un DBA MySQL à l&#8217;avenir, qui sait ?</p>
<p>Face à un tel défi, trois solutions :</p>
<p>- La fuite (mais faites une croix sur la &laquo;&nbsp;recommandation&nbsp;&raquo; Linkedin)<br />
- Le kernel panic<br />
- MySQL Sandbox !</p>
<p>Bien vu, MySQL Sandbox est la réponse la plus stratégique pour la poursuite de votre carrière.</p>
<p>Giuseppe Maxia (dont le blog figure dans notre blogroll, allez y jeter un oeil) est l&#8217;auteur de cet outil vraiment très pratique.  Que propose t-il ?</p>
<p>L&#8217;idée est d&#8217;automatiser l&#8217;installation de plusieurs serveurs MySQL sur une même machine. Rien que nous ne puissions faire manuellement c&#8217;est vrai, cependant la procédure habituelle consistant à ne pas mélanger les répertoires d&#8217;installation, choisir un port différent par serveur, appliquer <a href="http://www.dbnewz.com/2008/07/14/mysql_secure_installation-pratique-mais-non-parametrable/" target="_blank">mysql_secure_installation</a>&#8230; Tout cela gagnerait à être automatisé non ? De plus ces installations manuelles sont potentiellement sources d&#8217;erreurs.</p>
<p>MySQL Sandbox est compatible avec toutes les versions MySQL de la 3.23 à la 6.0. Les différentes installations effectuées sont indépendantes les unes des autres, on peut ainsi faire cohabiter sans risque de conflits plusieurs versions différentes de MySQL sur une même machine (ports, répertoires et sockets indépendants).</p>
<p>En plus d&#8217;automatiser ces processus d&#8217;installation (gain de temps), MySQL Sandbox ne s&#8217;arrête pas là et  propose également des commandes très simples pour gérer les serveurs une fois installés.</p>
<p>Concernant le gain de temps, son auteur promet (notamment en page 2 de cette <a href="http://datacharmer.org/presentations/mysqluniv_2008/sandbox_2_0.html" target="_blank">présentation</a>) l&#8217;installation d&#8217;une réplication MySQL en 15 secondes. Info ou intox ?</p>
<p><span id="more-75"></span></p>
<p><strong>Installation et pré-requis<br />
</strong></p>
<p>Pour fonctionner MySQL Sandbox n&#8217;a besoin que des binaries des versions que vous souhaitez installer.</p>
<p>L&#8217;installation est très rapide :</p>
<p>Après avoir téléchargé <a href="https://launchpad.net/mysql-sandbox" target="_blank">MySQL Sandbox</a>, il suffit de le décompresser dans le répertoire de votre choix :</p>
<p>debian:/opt# tar xzvf mysql_sandbox_2.0.11.tar.gz</p>
<p>On remarque alors que différentes commandes sont à notre disposition, plutôt explicites :</p>
<p><code>-rwxr-xr-x 1 501 staff  6154 2008-10-05 07:42 <strong>make_multiple_custom_sandbox</strong><br />
-rwxr-xr-x 1 501 staff  9062 2008-10-05 07:42 <strong>make_multiple_sandbox</strong><br />
-rwxr-xr-x 1 501 staff 12180 2008-10-05 07:42 <strong>make_replication_sandbox</strong><br />
-rwxr-xr-x 1 501 staff  5786 2008-10-05 07:42 <strong>make_sandbox</strong></code></p>
<p>make_sandbox : installe un serveur MySQL simple<br />
make_replication_sandbox : installe une réplication (par défaut un master, 2 slaves)<br />
make_multiple_sandbox : pour installer plusieurs serveurs identiques<br />
make_multiple_custom_sandbox : permet d&#8217;installer plusieurs serveurs de versions différentes</p>
<p><strong>Installer une réplication</strong></p>
<p>Une fois le <a href="http://dev.mysql.com/downloads/" target="_blank">binary récupéré</a>, nous utilisons la commande <strong>make_replication_sandbox</strong> pour obtenir un master et deux slaves. Elle prend en paramètre le tar.gz du binary (d&#8217;autres raccourcis sont possibles, je vous renvoie au fichier README de l&#8217;outil).</p>
<p><code>debian:/opt/mysql_sandbox_2.0.11# ./make_replication_sandbox /opt/mysql-5.0.67-linux-i686-glibc23.tar.gz</code></p>
<p>La sortie écran donne ceci :<br />
installing and starting master<br />
installing slave 1<br />
installing slave 2<br />
starting slave 1<br />
. sandbox server started<br />
starting slave 2<br />
.. sandbox server started<br />
initializing slave 1<br />
initializing slave 2<br />
replication directory installed on /root/sandboxes/rsandbox_5_0_67</p>
<p>C&#8217;est fait ! L&#8217;installation en elle-même a duré un peu plus de 15 secondes, disons que les lignes de commande à taper tiennent dans ce laps de temps&#8230;</p>
<p>Par défaut les &laquo;&nbsp;bacs à sable&nbsp;&raquo; installés par MySQL Sandbox se placent dans $HOME/sandboxes/. Dans le cadre de notre réplication, celle-ci a été installée ici : debian:~/sandboxes/rsandbox_5_0_67#</p>
<p>Notre réplication est d&#8217;ores et déjà fonctionnelle, on peut le vérifier en se connectant par exemple au slave numero 2 (faites un ps-ef | grep mysql pour afficher rapidement les noms/localisations des sockets par ex)</p>
<p>debian:/home/user# mysql &#8211;socket=/tmp/mysql_sandbox29473.sock -p</p>
<p>Le password par défaut est &laquo;&nbsp;msandbox&nbsp;&raquo;.</p>
<p>mysql&gt; show slave status\G<br />
Slave_IO_State: Waiting for master to send event<br />
Master_Host: 127.0.0.1<br />
Master_User: msandbox<br />
Master_Port: 29472<br />
Connect_Retry: 60<br />
Master_Log_File: mysql-bin.000001<br />
Read_Master_Log_Pos: 628<br />
Relay_Log_File: mysql_sandbox29473-relay-bin.000002<br />
Relay_Log_Pos: 765<br />
Relay_Master_Log_File: mysql-bin.000001<br />
<strong>Slave_IO_Running: Yes<br />
Slave_SQL_Running: Yes</strong></p>
<p>La réplication fonctionne, le pari est tenu !</p>
<p><strong>Les autres commandes disponibles</strong></p>
<p>Evoquées plus haut les commandes make_multiple_custom_sandbox, make_multiple_sandbox, make_sandbox et make_replication_sandbox vous permettent d&#8217;installer différentes topologies de serveurs MySQL, du master-master au groupe de serveurs aux versions identiques ou pas.</p>
<p>Exemple, pour installer la version MySQL 5.1.28 sur la même machine que notre réplication précédente :</p>
<p>debian:/opt/mysql_sandbox_2.0.11# ./make_sandbox /opt/mysql-5.1.28-rc-linux-i686-glibc23.tar.gz</p>
<p>Résultat :</p>
<p>&laquo;&nbsp;Your sandbox server was installed in /root/sandboxes/msb_5_1_28.&nbsp;&raquo;, simple non ?</p>
<p>D&#8217;autres commandes existent pour gérer votre installation :</p>
<p><strong>start, restart, stop, clear</strong>&#8230; un suffixe &laquo;&nbsp;_all&nbsp;&raquo; pour les réplications vient s&#8217;ajouter aux commandes précédentes, ex &laquo;&nbsp;<strong>stop_all</strong>&laquo;&nbsp;.</p>
<p>&laquo;&nbsp;m&nbsp;&raquo; est le raccourci de master, &laquo;&nbsp;s1&#8243;, &laquo;&nbsp;s2&#8243;, etc concernent les slaves.</p>
<p>Ainsi pour arrêter totalement notre configuration de réplication précédente, on effectue :</p>
<p>debian:~/sandboxes/rsandbox_5_0_67# ./stop_all</p>
<p>A l&#8217;écran :</p>
<p>executing &laquo;&nbsp;stop&nbsp;&raquo; on slave 1<br />
executing &laquo;&nbsp;stop&nbsp;&raquo; on slave 2<br />
executing &laquo;&nbsp;stop&nbsp;&raquo; on master</p>
<p>Comme vous le voyez, MySQL Sandbox est très simple d&#8217;emploi.</p>
<p>Pour aller plus loin je vous conseille vivement la lecture (c&#8217;est rapide) du <a href="http://forge.mysql.com/wiki/MySQL_Sandbox" target="_blank">wiki</a> de l&#8217;outil. Il reprend en fait le fichier README. Clair et concis vous y trouverez certainement votre bonheur : grâce à MySQL Sandbox, tester une nouvelle version de MySQL devient un jeu d&#8217;enfant.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dbnewz.com/2008/10/10/15-secondes-pour-installer-une-replication-mysql-avec-mysql-sandbox-pari-tenu/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Générer un jeu de données : shell, mysqlslap, et procédure stockée</title>
		<link>http://www.dbnewz.com/2008/08/19/generer-un-jeu-de-donnees-shell-mysqlslap-et-procedure-stockee/</link>
		<comments>http://www.dbnewz.com/2008/08/19/generer-un-jeu-de-donnees-shell-mysqlslap-et-procedure-stockee/#comments</comments>
		<pubDate>Mon, 18 Aug 2008 22:39:46 +0000</pubDate>
		<dc:creator>arnaud</dc:creator>
				<category><![CDATA[4.0]]></category>
		<category><![CDATA[4.1]]></category>
		<category><![CDATA[5.0]]></category>
		<category><![CDATA[5.1]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[index]]></category>
		<category><![CDATA[pratique]]></category>

		<guid isPermaLink="false">http://www.dbnewz.com/?p=61</guid>
		<description><![CDATA[Le prochain article de notre série consacrée aux index MySQL approche et j&#8217;ai besoin pour ce prochain épisode de générer une table de test de la forme suivante :  CREATE TABLE `t` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`date` timestamp NOT NULL,
`flag` tinyint(4) NOT NULL default '0',
PRIMARY KEY  (`id`),
KEY `flag` (`flag`)
) ENGINE=MyISAM;La structure est définie, [...]]]></description>
			<content:encoded><![CDATA[<p>Le prochain article de <a href="http://www.dbnewz.com/tag/index/" target="_blank">notre série consacrée aux index</a> MySQL approche et j&#8217;ai besoin pour ce prochain épisode de générer une table de test de la forme suivante :<br id="d7d0" /> <br id="zkp0" /> <code>CREATE TABLE `t` (<br />
`id` mediumint(8) unsigned NOT NULL auto_increment,<br />
`date` timestamp NOT NULL,<br />
`flag` tinyint(4) NOT NULL default '0',<br />
PRIMARY KEY  (`id`),<br />
KEY `flag` (`flag`)<br />
) ENGINE=MyISAM;</code><br id="yr-u" /><br id="yr-u0" />La structure est définie, reste à alimenter la table, disons 1 million d&#8217;enregistrements.<br id="ix.u" /> <br id="ix.u0" /> La valeur du champ &laquo;&nbsp;flag&nbsp;&raquo; est importante pour nos tests ultérieurs, sa valeur doit pour le moment être comprise entre 0 et 1, le tout à peu près uniformément distribué.<br id="g-s4" /> <br id="g-s40" /> La requête sera la suivante :<br id="ef7s" /> <br id="g-s41" /> <code>INSERT INTO test.t (flag) VALUES (ROUND(RAND()))</code>;<br id="d0-j" /> <br id="d0-j0" /> Il faut maintenant exécuter celle-ci 1 million de fois.<br id="gx_b" /> Voyons ce que cela donne en utilisant le shell, mysqlslap ou bien encore une procédure stockée.</p>
<p><span id="more-61"></span></p>
<p><strong>Le shell</strong></p>
<p>L&#8217;idée : générer un fichier texte des données à insérer puis exécuter le fichier de sortie comme entrée du client mysql.</p>
<p>Cette méthode n&#8217;est pas la plus efficace du lot, surtout pour 1 million de lignes, mais on peut néanmoins arriver à ses fins :</p>
<p><code>debian:/tmp# (for i in `seq 1 1000000`; do echo "insert into test.t(flag) values(round(rand()));"; done;) &gt; /tmp/insertions.txt</code></p>
<p>Puis :</p>
<p><code>debian:/tmp# mysql test &lt; /tmp/insertions.txt</code></p>
<p>Notre million de lignes est inséré.</p>
<p><strong>mysqlslap</strong></p>
<p>mysqlslap est un outil de benchmark que <a href="http://www.dbnewz.com/2008/07/07/mysqlslap-et-supersmack-deux-outils-de-benchmark-pour-mysql/" target="_blank">nous avons étudié récemment</a>. Nous détournons ici son utilisation première pour finalement exécuter notre million de requêtes :</p>
<p><code>debian:/usr/local/mysql51# ./bin/mysqlslap --user=root --socket=/tmp/mysql.sock --concurrency=1 --iterations=1000000 --query="insert into test.t (flag) values (round(rand()))"</code></p>
<p>Benchmark<br id="bel10" /> Average number of seconds to run all queries: 0.000 seconds<br id="bel11" /> Minimum number of seconds to run all queries: 0.000 seconds<br id="bel12" /> Maximum number of seconds to run all queries: 0.609 seconds<br id="bel13" /> Number of clients running queries: 1<br id="bel14" /> Average number of queries per client: 1</p>
<p>Cette solution est plus rapide que la précédente, aussi si vous disposez de mysqlslap, n&#8217;hésitez pas.</p>
<p><strong>La procédure stockée</strong> : REPEAT&#8230; UNTIL</p>
<p>Dès lors qu&#8217;on envisage d&#8217;insérer 1 million de lignes dans une table, la notion de &laquo;&nbsp;boucle&nbsp;&raquo; n&#8217;est jamais très loin, et finalement la procédure stockée non plus. Celle-ci est en effet un moyen simple et rapide d&#8217;implémenter un traitement répétitif.</p>
<p>Basique et à peine paramétrable (seul le nombre d&#8217;enregistrements à insérer est dynamique), voici à quoi ressemble la procédure stockée permettant d&#8217;insérer notre million de lignes :</p>
<p><code>delimiter //<br id="bfwc" />CREATE PROCEDURE fill_table(nb_rows INT)<br id="bfwc0" />BEGIN<br id="bfwc1" /> DECLARE i INT DEFAULT 0;<br id="bfwc2" /> REPEAT<br id="bfwc3" /> SET i = i + 1;<br id="bfwc4" /> INSERT INTO t (flag) VALUES(round(rand()));<br id="bfwc5" /> UNTIL i &gt;= nb_rows<br id="bfwc6" /> END REPEAT;<br id="bfwc7" />END;<br id="bfwc8" />//<br id="bfwc9" />delimiter ;</code><br id="bfwc10" /><br id="bfwc11" />Pas vraiment besoin de commenter le code, on note simplement les &laquo;&nbsp;delimiter&nbsp;&raquo; qui permettent de définir une autre terminaison que &laquo;&nbsp;;&nbsp;&raquo; le temps d&#8217;écrire la procédure dans le client mysql.</p>
<p>Pour appeler celle-ci :<br id="z6fd" /><br id="z6fd0" /><code>mysql&gt; CALL fill_table(1000000);</code><br id="z6fd1" />Query OK, 1 row affected (1 min 37.98 sec)</p>
<p>Cette solution est la plus rapide des trois présentées ici.</p>
<p>Mission accomplie ? Presque&#8230;</p>
<p>Avant de lancer la procédure stockée, la commande SHOW INDEX affichait une cardinalité de 0 pour la clé primaire et de NULL pour notre index situé sur &laquo;&nbsp;flag&nbsp;&raquo;.</p>
<p>Une fois la procédure terminée, un SHOW INDEX indique cette fois une cardinalité mise à jour pour la clé primaire (1 000 000) mais celle-ci est toujours à NULL pour l&#8217;index &laquo;&nbsp;flag&nbsp;&raquo;.</p>
<p>La commande <a href="http://dev.mysql.com/doc/refman/5.1/en/analyze-table.html" target="_blank">ANALYZE </a>permet de laver cet affront :</p>
<p><code>mysql&gt; ANALYZE TABLE t;<br />
+---------+---------+----------+----------+<br />
| Table   | Op      | Msg_type | Msg_text |<br />
+---------+---------+----------+----------+<br />
| world.t | analyze | status   | OK       |<br />
+---------+---------+----------+----------+</code></p>
<p>Les statistiques de notre index sont désormais à jour et la commande SHOW INDEX indique désormais une cardinalité de 2 pour l&#8217;index &laquo;&nbsp;flag&nbsp;&raquo;, le champ indexé ne comporte effectivement que des 0 ou des 1.</p>
<p>Nous voilà face à un index de cardinalité 2&#8230; Peu sélectif ? Inutile ? Mieux que rien ? Les paris sont ouverts.</p>
<p>Réponse au prochain numéro, stay tuned.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dbnewz.com/2008/08/19/generer-un-jeu-de-donnees-shell-mysqlslap-et-procedure-stockee/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Les index MySQL : types, placements, efficacité</title>
		<link>http://www.dbnewz.com/2008/06/27/les-index-mysql-types-placements-efficacite/</link>
		<comments>http://www.dbnewz.com/2008/06/27/les-index-mysql-types-placements-efficacite/#comments</comments>
		<pubDate>Fri, 27 Jun 2008 06:52:44 +0000</pubDate>
		<dc:creator>arnaud</dc:creator>
				<category><![CDATA[4.0]]></category>
		<category><![CDATA[4.1]]></category>
		<category><![CDATA[5.0]]></category>
		<category><![CDATA[5.1]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[index]]></category>
		<category><![CDATA[tuning]]></category>

		<guid isPermaLink="false">http://www.dbnewz.com/?p=48</guid>
		<description><![CDATA[Déjà trois semaines d&#8217;écoulées depuis que certains d&#8217;entre vous, les &#171;&#160;héros&#160;&#187;, ont posé leurs questions (oui il est possible de devenir un héros rien qu&#8217;en lisant dbnewz ! Les véritables héros sont d&#8217;ailleurs abonnés au tout nouveau flux feedburner   )
Trois semaines d&#8217;attente, cela mérite un billet digne de ce nom, c&#8217;est parti.
Indexer, pourquoi [...]]]></description>
			<content:encoded><![CDATA[<p>Déjà trois semaines d&#8217;écoulées depuis que certains d&#8217;entre vous, les &laquo;&nbsp;héros&nbsp;&raquo;, ont posé leurs questions (oui il est possible de <a href="http://www.dbnewz.com/2008/06/05/les-index-mysql-la-serie-dont-vous-etes-le-heros/" target="_blank">devenir un héros</a> rien qu&#8217;en lisant dbnewz ! Les véritables héros sont d&#8217;ailleurs abonnés au tout nouveau flux <a href="http://feeds.feedburner.com/Dbnewz" target="_blank">feedburner</a> <img src='http://www.dbnewz.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  )</p>
<p>Trois semaines d&#8217;attente, cela mérite un billet digne de ce nom, c&#8217;est parti.</p>
<p><strong>Indexer, pourquoi ?</strong><br id="dz-w" /><br id="yo1g" />L&#8217;indexation peut avoir plusieurs buts : <br id="gpy7" />- Accéder à ses données plus rapidement, les index sont en effet l&#8217;outil le plus puissant pour <strong>accélérer les temps d&#8217;exécution de vos requêtes</strong> jusqu&#8217;à parfois plusieurs centaines de % !<br id="gpy70" />- Définir le degré d&#8217;unicité d&#8217;une colonne donnée : chaque champ doit-il être unique ? les doublons sont-ils autorisés ?<br id="e0_r" /><br id="uby5" /><strong>Principe de fonctionnement</strong><br id="kvk1" /><br id="kvk10" />Lorsque vous envoyez une requête à votre serveur MySQL, celle-ci est d&#8217;abord confiée au &laquo;&nbsp;parseur&nbsp;&raquo; SQL qui a pour but de vérifier si la syntaxe de votre demande est correcte. Cette étape franchie, la requête passe par &laquo;&nbsp;l&#8217;optimiseur&nbsp;&raquo;. Il s&#8217;agit ici de déterminer le <strong>plan d&#8217;exécution</strong> de la requête afin que celle-ci s&#8217;exécute le plus rapidement possible.</p>
<p>L&#8217;optimiseur détecte si d&#8217;éventuels index sont disponibles, si c&#8217;est le cas il décidera de s&#8217;en servir&#8230; ou pas : il est parfois plus rapide de ne pas se servir d&#8217;un index <strong>!</strong> Nous verrons pourquoi au cours de cette série d&#8217;articles.</p>
<p>Une fois le plan d&#8217;exécution achevé, c&#8217;est le moteur de stockage qui prend le relais, celui-ci peut être vu comme un &laquo;&nbsp;module&nbsp;&raquo; de MySQL :</p>
<p><a href="http://dev.mysql.com/tech-resources/articles/mysql_5.0_psea1.html" target="_blank"><img class="alignnone" src="http://dev.mysql.com/tech-resources/articles/mysql_5.0_psea1.jpg" alt="Les moteurs de stockage MySQL sont des \" width="362" height="261" /></a></p>
<p><span id="more-48"></span>Pour schématiser, et dans un monde idéal, lorsqu&#8217;un index est disponible et &laquo;&nbsp;compatible&nbsp;&raquo; avec votre requête, l&#8217;optimiseur MySQL peut décider de l&#8217;utiliser afin d&#8217;éviter de parcourir l&#8217;ensemble des données des tables concernées.</p>
<p>Un exemple couramment employé pour illustrer ce propos consiste à imaginer la difficultée que nous aurions à retrouver quelqu&#8217;un dans l&#8217;annuaire si nous connaissions son nom mais pas l&#8217;alphabet (qui est notre index)&#8230; Transposé au monde informatique cela donne un serveur MySQL qui compare une à une les entrées du botin pour trouver toutes celles qui correspondent au nom recherché. Si au contraire ce nom est indexé, et si celui-ci commence par exemple par &#8216;T&#8217;, le serveur sait directement qu&#8217;il doit démarrer sa recherche à partir du &#8216;T&#8217;. Imaginez l&#8217;impact en terme de gain de temps lorsque plusieurs jointures sont concernées : deux tables de 10 000 lignes chacune forment un produit cartésien de 100 000 000 lignes environ à étudier&#8230;<br id="mxtu" /><br id="mxtu0" />Les index n&#8217;ont hélas pas que des avantages :<br id="mxtu4" />- Les opérations de mises à jour (INSERT, UPDATE, DELETE) sont en effet ralenties puisqu&#8217;en plus des données, les index doivent eux aussi être mis à jour lors de ces opérations, c&#8217;est le prix à payer&#8230; Ce prix peut néamoins se &laquo;&nbsp;négocier&nbsp;&raquo;, nous verrons cela plus tard.<br id="q.-8" /><br id="q.-80" /><strong>Notre terrain de jeu, la base &laquo;&nbsp;world&nbsp;&raquo;</strong><br id="w4ef" /></p>
<p>MySQL propose au téléchargement plusieurs bases d&#8217;exemple dont <a href="http://dev.mysql.com/doc/" target="_blank">&laquo;&nbsp;world&nbsp;&raquo; et &laquo;&nbsp;sakila&nbsp;&raquo;</a>. Elles épargnent le soin aux utilisateurs de MySQL souhaitant tester quelques requêtes de se constituer eux-mêmes une base de test, celles-ci sont prêtes à l&#8217;emploi.</p>
<p>Nous utiliserons pour nos tests la base &laquo;&nbsp;world&nbsp;&raquo;. Très simple puisque constituée uniquement de trois petites tables MyISAM (Country, CountryLanguage et City), elle permet de se concentrer uniquement sur les index sans perdre de temps à assimiler un schéma plus complexe.<br id="m4x6" /><br id="m4x60" />Si vous souhaitez transformer le script de création SQL de la base &laquo;&nbsp;world&nbsp;&raquo; en une version graphique &laquo;&nbsp;presque&nbsp;&raquo; MCD (les relations entre les tables ne sont pas générées automatiquement pour cette base), le billet précédent est fait pour vous, <a href="http://www.dbnewz.com/2008/06/22/dbdesigner-4-generer-son-mcd-par-reverse-engineering/" target="_blank">les étapes d&#8217;installation et de génération du MCD par &laquo;&nbsp;reverse engineering&nbsp;&raquo; avec DBDesigner 4</a> y sont décrites.<br id="lfl2" /><br id="lfl20" />Voici ce qu&#8217;on peut obtenir pour cette base à partir de DBDesigner :<br id="lfl21" /><br id="lfl22" /><a href="http://www.dbnewz.com/wp-content/uploads/2008/06/world_db_small.png" target="_blank"><img class="alignnone size-thumbnail wp-image-50" title="world_db_small" src="http://www.dbnewz.com/wp-content/uploads/2008/06/world_db_small-150x150.png" alt="" width="150" height="150" /></a><br id="lfl23" /><br id="lfl24" /></p>
<p><strong id="xz5z">Quel type d&#8217;index choisir : PRIMARY KEY, UNIQUE, ou INDEX ?</strong><br id="txto" /><br id="txto0" />Choisissez le type de vos index avec soin :<br id="txto1" />- Une clé primaire (<strong>PRIMARY KEY</strong>) est strictement unique, les NULL ne sont pas autorisés.<br id="e.px" />- Un index de type <strong>UNIQUE </strong>est comparable à une clé primaire, mis à part pour les valeurs NULL puisque celles-ci sont autorisées (et potentiellement en plusieurs occurences).<br id="fy.m" />- Un index de type <strong>INDEX </strong>ou <strong>KEY </strong>(c&#8217;est un alias) signifie simplement que l&#8217;on souhaite indexer une colonne susceptible de contenir des doublons.<br id="blrx" /><br id="blrx0" />Les index de type <strong>FULLTEXT</strong> et <strong>SPATIAL</strong> sont particuliers et méritent un épisode à eux seuls, ils seront donc évoqués ultérieurement.<br id="k7_h" /><br id="k7_h0" />Passons rapidement sur l&#8217;étape de <a href="http://dev.mysql.com/doc/refman/5.0/fr/create-index.html" target="_blank">déclaration d&#8217;un index</a>, celle-ci s&#8217;effectue soit au moment de la création de la table, soit plus tard comme ici :<br id="or3." /><br id="or3.0" />mysql&gt; <code>CREATE INDEX idx_district ON City (District);<br id="n0.-" />Query OK, 4079 rows affected (0.04 sec)<br id="n0.-0" />Records: 4079  Duplicates: 0  Warnings: 0</code><br id="n0.-1" /><br id="n0.-2" />Nous venons de créer un index de type INDEX (autorise les doublons) sur la colonne District de la table City.<br id="n0.-3" /><br id="n0.-4" />Attention, si nous avions tenté la même chose avec un index de type UNIQUE&#8230;<br id="l3as" /><br id="l3as0" />mysql&gt; <code>CREATE UNIQUE INDEX idx_district ON City (District);<br id="l3as1" />ERROR 1062 (23000): Duplicate entry 'Zuid-Holland' for key 2</code><br id="dh1k" /><br id="dh1k0" />&#8230; MySQL nous signale qu&#8217;il y&#8217;a déjà des doublons dans la colonne District, impossible donc de créer un index de type UNIQUE sur celle-ci.<br id="najp" /><br id="najp0" /><strong>Pour supprimer cet index :</strong><br id="najp1" />mysql&gt; <code>DROP INDEX idx_district ON City;</code><br id="a8y02" />Ou :<br id="a8y04" />mysql&gt; <code>ALTER TABLE City DROP INDEX idx_district;</code><br id="bim:" /><strong><br id="bim:0" />Pour visualiser les index d&#8217;une table :</strong><br id="zw.m" /><br id="zw.m0" />mysql&gt; SHOW INDEX FROM Country;</p>
<p><strong>Attention aux doublons !</strong><br id="zw.m17" /><br id="bim:2" />Inutile de rajouter un index de type &laquo;&nbsp;INDEX&nbsp;&raquo; ou encore &laquo;&nbsp;UNIQUE&nbsp;&raquo; sur un champ qui est déjà clé primaire par exemple&#8230; Vous dupliqueriez inutilement les index avec à la clé un gaspillage d&#8217;espace disque/mémoire, des ralentissements inutiles lors des mises à jour, davantage de travail pour l&#8217;optimiseur&#8230;<br id="fq0r" /><br id="p-i7" /><strong id="kw9g2">Quels types de champ indexer ?</strong><br id="bo1r" /><br id="bo1r0" />INT, VARCHAR, BLOB&#8230; ? Quels sont les meilleurs candidats à l&#8217;indexation ?</p>
<p><strong>Plus l&#8217;index est court, mieux c&#8217;est</strong> : un index est en permanence comparé à d&#8217;autres valeurs (celles recherchées), ces comparaisons sont plus rapides si la zone à comparer est plus courte. Des index concis occupent également moins de place sur disque, génèrent moins d&#8217;I/O (activité disque s&#8217;ils ne sont pas en mémoire) et peuvent ainsi être stockés en plus grand nombre dans une même quantité de RAM (pensez au <a href="http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#option_mysqld_key_buffer_size" target="_blank">key_buffer_size</a> de MyISAM par exemple).<br id="e1fk" /><br id="e1fk0" />Bref, si vous désirez stocker une liste de noms de villes sous forme de chaînes de caractères, sachez qu&#8217;il est inutile de réserver un champ de type CHAR(255) : rares sont celles qui atteindront cette longueur, pensez plutôt au VARCHAR qui s&#8217;adaptera à la longueur de vos valeurs.<br id="g6j1" />Plus malin encore, lors de la conception de votre base de données, intéressez-vous aux différentes formes de normalisation : 1NF, 2NF, 3NF, ces méthodes permettent d&#8217;obtenir un schéma qui permet de partir sur de bonnes bases.<br id="ist_" />En gardant cet exemple des villes, si vous stockez dans une table &laquo;&nbsp;inscrits&nbsp;&raquo; toutes les infos contextuelles à un utilisateur, dont sa ville, envisagez de stocker dans une table &laquo;&nbsp;ville&nbsp;&raquo;, toutes les infos qui s&#8217;y rapportent : nom, population, etc. Reliez ensuite votre table &laquo;&nbsp;inscrits&nbsp;&raquo; à la table &laquo;&nbsp;ville&nbsp;&raquo; par la valeur de la clé primaire de ville et vous supprimerez ainsi tous ces libellés de villes identiques au profit d&#8217;un ID bien plus rapide et économique.<br id="yxd7" /></p>
<p><strong>Soyez radins !</strong></p>
<p>Vos index seront d&#8217;autant plus efficaces s&#8217;ils sont apposés sur des champs bien adaptés à vos données. <strong>Ne gaspillez pas le capital &laquo;&nbsp;performance&nbsp;&raquo; de vos index</strong> en utilisant un INT pour stocker par exemple la vitesse légale sur autoroute en France (par temps sec) : 130 km/h&#8230;  Un TINY INT UNSIGNED suffira (permet de stocker les valeurs de 0 à 255). Un INT permet lui de stocker des valeurs comprises entre <code id="cps40" class="literal" style="font-family: Verdana;">-2.147.483.648</code> <code id="cps42" class="literal" style="font-family: Verdana;">2.147.483.647, et en rajoutant l'attri</code>but UNSIGNED, on obtient un rayon d&#8217;action de 0 à plus de 4 milliards ! A quoi bon utiliser un INT dans cet exemple ? Quand on sait de plus qu&#8217;un INT occupe quatre fois plus de place qu&#8217;un TINY INT, l&#8217;impact sur les performances et la perte d&#8217;espace avec une table de plusieurs millions d&#8217;enregistrements est évident&#8230;</p>
<p>Prenez connaissance des <a href="http://dev.mysql.com/doc/refman/5.0/en/numeric-types.html" target="_blank">caractéristiques des types de données</a> que vous utilisez. Visualisez également <a href="http://dev.mysql.com/doc/refman/5.0/fr/storage-requirements.html" target="_blank">la taille requise</a>, c&#8217;est un élement qui peut s&#8217;avérer dissuasif.<br id="x-cm" /><br id="x-cm0" />Pour résumer, n&#8217;indexez pas une colonne en fonction de son type, mais prenez soin dans un premier temps de définir celles-ci avec le type de données qui leur convient le mieux, le plus économique. Prévoyez une marge néanmoins : n&#8217;utilisez pas un TINY INT même UNSIGNED pour un identifiant de clé primaire AUTO_INCREMENT concernant une newsletter d&#8217;un grand service commercial : si tout se passe bien vous devriez rapidement dépasser le seuil des 255 inscrits&#8230; Le type de données juste &laquo;&nbsp;au-dessus&nbsp;&raquo;, SMALLINT UNSIGNED, qui permet d&#8217;aller jusqu&#8217;à 65535, est sans doute plus confortable.<br id="t9cg" /><br id="t9cg0" /><strong id="n1bv">Le tips dbnewz : </strong>utilisez la commande <strong id="dwmm">PROCEDURE ANALYSE()</strong><br id="n1bv0" /><br id="n1bv1" />Cette commande analyse pour vous vos tables et vous propose le type idéal pour vos données&#8230; si vous en avez bien sûr, ça ne peut pas vous aider lors d&#8217;une création de table. En revanche, elle permet &laquo;&nbsp;d&#8217;auditer&nbsp;&raquo; vos enregistrements actuels, d&#8217;en tirer quelques statistiques et propose le type le plus adapté :<br id="n3yt" /><br id="uv4e" />mysql&gt; <code>SELECT Name FROM Country PROCEDURE ANALYSE(10,256)\G<br id="uv4e1" /> Field_name: world.Country.<strong>Name</strong><br id="uv4e2" /> Min_value: Afghanistan<br id="uv4e3" /> Max_value: Zimbabwe<br id="uv4e4" /> <strong>Min_length: 4</strong><br id="uv4e5" /> <strong>Max_length: 44</strong><br id="uv4e6" /> Empties_or_zeros: 0<br id="uv4e7" /> Nulls: 0<br id="uv4e8" /><strong>Avg_value_or_avg_length: 10.0962</strong><br id="uv4e9" /> Std: NULL<br id="uv4e10" /> <strong>Optimal_fieldtype</strong>: VARCHAR(44) NOT NULL<br id="uv4e11" />1 row in set (0.00 sec)</code><br id="uv4e12" /><br id="n3yt0" />Vous pouvez bien sûr effectuer cette requête sur l&#8217;intégralité des champs de l&#8217;une de vos tables (SELECT *&#8230;)<br id="lgar" />Les paramètres fournis à <a href="http://dev.mysql.com/doc/refman/5.1/en/procedure-analyse.html" target="_blank">PROCEDURE ANALYSE ()</a> sont à modifier en fonction de vos souhaits. Par défaut cette fonction a tendance à vouloir transformer toutes vos chaînes de caractères en champs <a href="http://dev.mysql.com/doc/refman/5.1/en/enum.html" target="_blank">ENUM</a> (stockés sous forme numérique en interne), à vous de définir combien de champs ENUM vous êtes prêts à utiliser. Réservez-les pour les cas où le champ représente une courte liste &laquo;&nbsp;fermée&nbsp;&raquo;, ex &laquo;&nbsp;M&nbsp;&raquo; ou &laquo;&nbsp;F&nbsp;&raquo;, les jours de la semaine par exemple, etc.<br id="hj59" /><br id="hj590" /><strong id="ny9g">Où placer ses index : quels sont les champs à indexer ?</strong><br id="ny9g0" /><br id="ny9g1" />Les champs concernés par une clause <strong>WHERE, ORDER BY, GROUP BY, MIN(), MAX()</strong>, ainsi que les champs qui permettent de <strong>relier des tables entre elles</strong>, sont de bons candidats à l&#8217;indexation, exemple :<br id="abxv" /><br id="aln7" /><code>SELECT ci.Name, ci.Population <br id="aln70" />FROM City ci INNER JOIN Country co ON ci.CountryCode = co.Code<br id="aln71" />WHERE ci.Population &gt; 5000000<br id="aln72" />ORDER BY ci.District ASC LIMIT 3</code><br id="aln73" /><br id="ulja" />- Le champ CountryCode de la table City ainsi que le champ Code de la table Country sont tous les deux à indexer. C&#8217;est d&#8217;ailleurs le cas ici puisque ces deux champs sont respectivement clés primaires de la table City et Country.<br id="ulja0" />- Le champ Population est intéressant à indexer, il permet à MySQL de parcourir très rapidement les villes par leur population triée et évite de comparer l&#8217;intégralité des populations de chaque ville, une à une.<br id="fv9-" />- Le champ District est également un candidat à l&#8217;indexation, il peut aider MySQL à trier les données plus rapidement.<br id="o0-s" /><br id="o0-s0" />A retenir : on indexe en priorité les champs impliqués dans les clauses évoqués ci-dessus (en gras), pas forcément ceux présents dans le SELECT.<br id="aln75" /><br id="o98j6" /><strong>Les index composés (ou multiples) et la règle du leftmost prefixing</strong><br id="ebx3" /><br id="ebx30" />&laquo;&nbsp;Faut-il préférer un index unique ou composé&nbsp;&raquo; était <a href="http://www.dbnewz.com/2008/06/05/les-index-mysql-la-serie-dont-vous-etes-le-heros/#comments" target="_blank">l&#8217;une des questions posées</a> par l&#8217;un d&#8217;entre vous il y&#8217;a quelques semaines&#8230;<br id="zkm0" /><br id="zkm00" />Un index composé doit se construire en fonction des requêtes que vous effectuez sur la table concernée.<br id="ku.e" />Prenons pour exemple la table City et ses cinq champs (ID, Name, CountryCode, District, Population).<br id="ku.e0" /><br id="ku.e1" />Si les seules requêtes que vous avez sur City sont du type :</p>
<p><code>SELECT ... FROM City WHERE Name = "..."</code></p>
<p>&#8230; Indexez Name et tout ira bien.</p>
<p>Si en revanche il vous arrive de trier non seulement sur &laquo;&nbsp;Name&nbsp;&raquo; mais également sur le code du pays :</p>
<p><code>SELECT ... FROM City WHERE Name = "..." AND CountryCode = "..."</code><br id="f50i0" /><br id="f50i1" />Dans ce cas, plutôt que de laisser MySQL comparer tous les CountryCode de la table avec votre recherche (ex : &laquo;&nbsp;FRA&nbsp;&raquo;), indexez la colonne CountryCode&#8230; Oui mais pas toute seule !<br id="lkbv" />Considérez en effet pour l&#8217;instant que MySQL n&#8217;utilise qu&#8217;un index par table, l&#8217;optimiseur MySQL choisit donc le plus restrictif afin que votre requête s&#8217;exécute le plus rapidement possible (nous verrons plus tard les cas particuliers où MySQL peut tirer parti de plusieurs index).<br id="w0mb" />Conséquence, il vous faut trouver un index qui soit utilisable pour vos deux critères de recherche : &laquo;&nbsp;Name&nbsp;&raquo; et &laquo;&nbsp;CountryCode&nbsp;&raquo;. La solution : créez un index multiple sur ces deux champs.<br id="tilr" /><br id="tilr0" />Dès lors que vous utilisez un index multiple, <strong>la règle </strong><strong>du leftmost prefixing</strong> rentre en jeu. Trop souvent méconnue, elle permet pourtant de créer ses index de façon efficace et d&#8217;éviter les doublons.<br id="ny9g2" /><br id="mqai" />Afin d&#8217;illustrer cette règle, ajoutons cette fois à la table City un index multiple sur les champs Name, CountryCode, District et Population :</p>
<p>mysql&gt; <code>CREATE INDEX name_cc_dis_pop ON City (Name, CountryCode, District, Population);</code><br id="ub980" /></p>
<p>Voici ce que l&#8217;on obtient avec le <strong>SHOW INDEX</strong> correspondant (la clé primaire existait déjà à la création de la table, ci-dessous une vue partielle des résultats réels) :</p>
<p>mysql&gt; <code>SHOW INDEX FROM City;<br id="cvh60" /></code></p>
<p>|<code> <strong>Key_name</strong> | <strong>Seq_in_index</strong> | <strong>Column_name</strong> <br id="cvh62" />+-------+------------+-----------------+</code></p>
<p><code><strong>|name_cc_dis_pop</strong> |   <strong>1</strong> |  <strong>Name</strong> </code></p>
<p><strong>|</strong><code><strong>name_cc_dis_pop</strong> |   <strong>2</strong> | <strong>CountryCode</strong> </code></p>
<p><code><strong>|</strong><strong>name_cc_dis_pop</strong> |   <strong>3</strong> | <strong>District</strong> </code></p>
<p><code> <strong>|name_cc_dis_pop</strong> |   <strong>4</strong> | <strong>Population</strong> |  <br id="cvh68" />+-------+------------+-----------------+</code></p>
<p>On remarque par rapport au SHOW INDEX précédent que cette fois-ci nous avons la colonne &laquo;&nbsp;Seq_in_index&nbsp;&raquo; qui s&#8217;incrémente pour chaque colonne qui compose notre index multiple. La position de chaque index dans cette séquence a une importance, c&#8217;est ce que nous allons voir maintenant.</p>
<p>Tel quel, cet index multiple sera potentiellement utilisé pour les requêtes de ce type :</p>
<p><code>SELECT ... FROM City WHERE Name = ... AND CountryCode = ... AND District = ... AND Population = ...<br id="w2qj" />SELECT ... FROM City WHERE Name = ... AND CountryCode = ... AND District = ... <br id="w2qj0" />SELECT ... FROM City WHERE Name = ... AND CountryCode = ... <br id="w2qj1" />SELECT ... FROM City WHERE Name = ...</code><br id="w2qj2" /><br id="w2qj3" />Une fois cette &laquo;&nbsp;logique&nbsp;&raquo; acquise, on comprend qu&#8217;il est inutile de rajouter un index sur Name par exemple puisque cette colonne est déjà indexée grâce à cet index multiple. Idem pour notre exemple précédent  d&#8217;index multiple concernant les champs Name et CountryCode, là encore inutile de recréer un index sur ces deux champs puisque ces derniers sont déjà représentés dans notre dernier exemple.<br id="niuy" /><br id="niuy0" />En revanche, si l&#8217;ordre de vos champs ne respecte pas l&#8217;ordre de séquence de votre index, comme ici :</p>
<p><code>SELECT ... FROM City WHERE Name = ... AND Population = ..</code></p>
<p>Cette requête ne bénéficiera pas complètement de l&#8217;index multiple précedemment crée, cela dit l&#8217;optimiseur tirera sûrement parti de cet index pour la colonne Name, mais pas pour le second critère de recherche.<br id="ewwh0" /><br id="ewwh1" />De même si votre requête est du type :</p>
<p><code>SELECT ... FROM City WHERE CountryCode = ...<br id="ewwh3" />SELECT ... FROM City WHERE District = ...<br id="ewwh4" />SELECT ... FROM City WHERE Population = ...<br id="ewwh5" />SELECT ... FROM City WHERE CountryCode = ... AND District = ... AND Population = ...</code><br id="ewwh6" /></p>
<p>&#8230; et autres variations qui ne débutent pas avec &laquo;&nbsp;Name&nbsp;&raquo; et ne respectent pas ensuite l&#8217;ordre de séquence de l&#8217;index (Name, CountryCode, District, et Population), l&#8217;index ne sera pas utilisé.<br id="z9sx" /><br id="z9sx0" />En conséquence, il est donc tout à fait légitime d&#8217;indexer par ailleurs la colonne Population seule si vous avez des requêtes du type :</p>
<p><code>SELECT ... FROM City WHERE Population &gt; ... </code><br id="p_16" /><br id="ny9g4" /><strong>Mesurez l&#8217;efficacité des index avec EXPLAIN</strong><br id="n6b2" /></p>
<p>Impossible d&#8217;évoquer les index sans parler de la commande <strong>EXPLAIN</strong>. Absolument <strong id="kjkb">fondamentale</strong>, elle affiche le plan d&#8217;exécution décidé par l&#8217;optimiseur MySQL et vous permet de mesurer si oui ou non vos index sont réellement utilisés.<br id="tqy0" /><br id="tqy00" />Reprenons une des premières requêtes de ce billet et rajoutons-lui le mot clé EXPLAIN :<br id="fo2v" />(on considère ici que la table City ne contient que sa clé primaire, pas les index rajoutés précedemment)</p>
<p>mysql&gt; <code><strong>EXPLAIN </strong>SELECT ci.Name, ci.Population<br id="dhkz" />FROM City ci INNER JOIN Country co ON ci.CountryCode = co.Code<br id="dhkz0" />WHERE ci.Population &gt; 5000000<br id="dhkz1" />ORDER BY ci.District ASC LIMIT 3\G<br id="dhkz2" /></code></p>
<p><code>*************************** 1. row *************<br />
id: 1<br />
select_type: SIMPLE<br />
table: ci<br />
type: ALL<br />
<strong>possible_keys: NULL</strong><br />
key: NULL<br />
key_len: NULL<br />
ref: NULL<br />
<strong>rows: 4079</strong><br />
Extra: Using where; Using filesort<br />
*************************** 2. row *************<br />
id: 1<br />
select_type: SIMPLE<br />
table: co<br />
type: eq_ref<br />
<strong>possible_keys: PRIMARY</strong><br />
<strong>key: PRIMARY</strong><br />
key_len: 3<br />
<strong>ref: world.ci.CountryCode</strong><br />
<strong>rows: 1</strong><br />
<strong>Extra: Using index</strong><br />
2 rows in set (0.00 sec)</code></p>
<p>La commande EXPLAIN sera étudiée plus précisemment dans un autre épisode, pour le moment contentons-nous de prêter attention aux champs en gras :</p>
<p>- Sur la première ligne le type ALL signale que MySQL doit effectuer un &laquo;&nbsp;full table scan&nbsp;&raquo; c&#8217;est à dire parcourir entièrement la table City qui compte 4079 enregistrements, ceci afin de repérer quelles sont les villes qui ont une population supérieure à 5M d&#8217;habitants. Aucun index/key n&#8217;a pu être utilisé (possible_keys : NULL) pour résoudre cette partie de la requête. La colonne &laquo;&nbsp;rows&nbsp;&raquo; indique le nombre approximatif d&#8217;enregistrements que MySQL pense devoir analyser pour mener à bien l&#8217;opération.</p>
<p>- La seconde ligne nous indique que cette fois MySQL a un candidat pour l&#8217;indexation, il s&#8217;agit de la clé primaire de la table Country, la jointure s&#8217;effectuant avec le champ &laquo;&nbsp;CountryCode&nbsp;&raquo; de la table City, qui est également une clé primaire. Résultat : MySQL effectue la correspondance très rapidement (rows : 1 et extra : Using index).<br id="sewv" /><br id="sewv0" />Ceci répond à une des questions posées précedemment par un lecteur : &laquo;&nbsp;Quand préférer le FULL TABLE SCAN à l&#8217;index ?&nbsp;&raquo; C&#8217;est en fait le travail de l&#8217;optimiseur, il doit déterminer si oui ou non un index vous fera gagner du temps. Il se peut qu&#8217;il se trompe (rarement), nous verrons comment orienter ses choix si besoin.<br id="ai:q" /><br id="ai:q0" />Rajoutons maintenant un index de type &laquo;&nbsp;INDEX&nbsp;&raquo; sur la colonne Population :<br id="ai:q1" /></p>
<p>mysql&gt; <code>CREATE INDEX idx_pop ON City (Population);</code><br id="j6rd" /><br id="j6rd0" />Puis appliquons à nouveau la même commande EXPLAIN, on obtient cette fois :</p>
<p><code>*************************** 1. row ************<br />
id: 1<br />
select_type: SIMPLE<br />
table: ci<br />
type: range<br />
<strong>possible_keys: idx_pop</strong><br />
<strong>key: idx_pop</strong><br />
key_len: 4<br />
ref: NULL<br />
<strong>rows: 25</strong><br />
Extra: Using where; Using filesort<br />
*************************** 2. row ************<br />
id: 1<br />
select_type: SIMPLE<br />
table: co<br />
type: eq_ref<br />
<strong>possible_keys: PRIMARY<br />
key: PRIMARY</strong><br />
key_len: 3<br />
ref: world.ci.CountryCode<br />
<strong>rows: 1</strong><br />
Extra: Using index<br />
2 rows in set (0.02 sec)<br id="ecl19" /></code><br id="ecl110" />Notre index a permis à MySQL de lire <strong>160 fois moins de lignes</strong> cette fois-ci par rapport à l&#8217;exemple précédent&#8230; Seules 25 lignes de la table City sont lues désormais (au lieu des 4079 lignes précedemment parcourues). C&#8217;est un gain très intéressant en termes de ressources serveur ! Amateurs de chiffres, des benchmarks sont prévus dans la suite de cette série.<br id="laec" /><br id="laec0" />Afin de patienter jusqu&#8217;aux prochains épisodes justement, vous pouvez commencer par appliquer les quelques conseils de ce billet tout en relisant pourquoi pas l&#8217;article concernant <a href="http://www.dbnewz.com/2008/05/19/choisir-limplementation-de-ses-index-b-tree-ou-hash-quelles-differences/" target="_blank">l&#8217;implémentation des index (BTREE ou HASH)</a> selon le type de votre moteur de stockage (MyISAM, InnoDB ou MEMORY). <br id="dhkz10" /><br id="m:ru" />Il reste certaines de vos questions en suspens, elles ne sont pas oubliées et seront débattues ici très prochainement.</p>
<p>Si vous avez des questions ou des remarques concernant cette première étape, n&#8217;hésitez pas.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dbnewz.com/2008/06/27/les-index-mysql-types-placements-efficacite/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>DBDesigner 4 : générer son MCD par reverse engineering</title>
		<link>http://www.dbnewz.com/2008/06/22/dbdesigner-4-generer-son-mcd-par-reverse-engineering/</link>
		<comments>http://www.dbnewz.com/2008/06/22/dbdesigner-4-generer-son-mcd-par-reverse-engineering/#comments</comments>
		<pubDate>Sun, 22 Jun 2008 10:54:07 +0000</pubDate>
		<dc:creator>arnaud</dc:creator>
				<category><![CDATA[4.0]]></category>
		<category><![CDATA[4.1]]></category>
		<category><![CDATA[5.0]]></category>
		<category><![CDATA[5.1]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[outils]]></category>
		<category><![CDATA[pratique]]></category>

		<guid isPermaLink="false">http://www.dbnewz.com/?p=46</guid>
		<description><![CDATA[Disposer d&#8217;un MCD (modèle conceptuel de données) lorsqu&#8217;on travaille sur une requête SQL impliquant différentes tables représente un gain de temps.Il est en effet plus rapide de jeter un coup d&#8217;oeil sur un MCD afin de repérer quels sont les champs qui lient une table à une autre plutôt que d&#8217;enchaîner les &#171;&#160;DESC ma_table&#160;&#187;, puis [...]]]></description>
			<content:encoded><![CDATA[<p>Disposer d&#8217;un MCD (modèle conceptuel de données) lorsqu&#8217;on travaille sur une requête SQL impliquant différentes tables représente un <strong id="tqz_">gain de temps</strong>.<br id="d0eo" />Il est en effet plus rapide de jeter un coup d&#8217;oeil sur un MCD afin de repérer quels sont les champs qui lient une table à une autre plutôt que d&#8217;enchaîner les &laquo;&nbsp;DESC ma_table&nbsp;&raquo;, puis repérer la clé primaire et les éventuelles clés étrangères, et rebolote sur la ou les tables de destination&#8230;<br id="ixuk" /><br id="ixuk0" />La prochaine série d&#8217;articles sur les index MySQL va nous amener à enchaîner quelques requêtes sur une des deux bases d&#8217;exemple disponibles sur le site de MySQL : <a href="http://dev.mysql.com/doc/" target="_blank">world et sakila</a>, le prétexte est donc tout trouvé pour évoquer ici la solution que j&#8217;ai retenu pour obtenir le MCD de ces tables : DBDesigner 4.</p>
<p>Cet outil n&#8217;est pas nouveau, son successeur officiel est même déjà connu, il s&#8217;agit de <a href="http://dev.mysql.com/workbench/" target="_blank">MySQL Workbench</a>. Celui-ci n&#8217;étant pas encore disponible sous linux, nous utiliserons son ancêtre et plus particulièrement sa fonctionnalité de &laquo;&nbsp;reverse engineering&nbsp;&raquo; : une fois connecté à votre base, DBDesigner 4 va générer sous forme graphique vos tables, leurs descriptions, et si tout se passe bien, les relations entre vos tables.</p>
<p><span id="more-46"></span><strong>Installation (fastidieuse) sous linux</strong><br id="m-dl0" /><br id="m-dl1" />L&#8217;installation de DBDesigner 4 sous linux (ubuntu 8.04 pour ma part) n&#8217;est pas de tout repos&#8230; J&#8217;ai rencontré toutes les erreurs potentielles croisées sur les différents tutoriels sur le sujet. Résultat des courses : il apparaît plus simple d&#8217;installer DBDesigner 4 en passant par <a href="http://www.winehq.org/" target="_blank">wine</a>, les <strong>problèmes de librairies manquantes</strong> disparaissent et les polices sont plus travaillées.<br id="swio" />Si néanmoins vous souhaitez vous passer de wine, voici quelques pistes : <a href="http://wiki.splitbrain.org/dbdesigner" target="_blank">http://wiki.splitbrain.org/dbdesigner</a> et un <a href="http://ubuntuforums.org/showthread.php?t=125911" target="_blank">how-to</a> tiré des forums ubuntu. Des solutions sont proposées pour ces fameuses libraries manquantes, cela dit j&#8217;avais toujours des problèmes malgré ces manipulations.<br id="tw3i" /><br id="tw3i0" />Une fois wine installé (<code>apt-get install wine</code>), téléchargez simplement <a href="http://www.fabforce.net/downloads.php" target="_blank">le fichier d&#8217;installation de DBDesigner 4</a> pour windows.</p>
<p>L&#8217;installation s&#8217;effectue simplement :</p>
<p><code>root@u200:/opt# wine DBDesigner4.0.5.6_Setup.exe</code> <br id="lq1_" /><br id="vkpd" />Si vous êtes sous MySQL 5, vous devez <strong>modifier le mot de passe</strong> de l&#8217;utilisateur à partir duquel vous vous connectez à DBDesigner de la façon suivante :<br id="vkpd0" /><br id="lq1_0" />mysql&gt; <code>SET PASSWORD FOR 'dbdesign'@'localhost' = OLD_PASSWORD('dbdesign');</code></p>
<p>Depuis sa version 5, MySQL utilise en effet un mécanisme d&#8217;authentification qui est incompatible avec les versions précédentes (&lt; 4.1). Afin d&#8217;assurer une rétro compatibilité, il est néanmoins possible avec MySQL 5 d&#8217;utiliser la commande &laquo;&nbsp;<a href="http://dev.mysql.com/doc/refman/5.1/en/encryption-functions.html#function_old-password" target="_blank">OLD_PASSWORD</a>&laquo;&nbsp;, le format utilisé pour le mot de passe sera alors compatible avec MySQL 4 (short hash contre long hash pour MySQL 5).<br id="fvds" /><br id="rwen" />Lancement de l&#8217;application:</p>
<p><code>root@u200:~/.wine/drive_c/Program Files/fabFORCE# wine DBDesigner4.exe</code></p>
<p><strong>Obtenir le schéma de sa base</strong></p>
<p>Pour générer votre MCD, et selon votre langue d&#8217;installation :</p>
<p>- Choisissez le menu &laquo;&nbsp;Database&nbsp;&raquo;, puis &laquo;&nbsp;Reverse Engineering&nbsp;&raquo;.</p>
<p>- Selectionnez une connexion à la base de données ou créez la vôtre : &laquo;&nbsp;Localhost 127.0.0.1&#8243; par exemple, puis renseignez vos login/pwd et validez, n&#8217;oubliez pas la commande &laquo;&nbsp;OLD_PASSWORD&nbsp;&raquo; si besoin.</p>
<p>- La fenêtre &laquo;&nbsp;Reverse Engineering&nbsp;&raquo; affiche alors la liste des tables de la base, par défaut elles sont toutes cochées. Remarquez un peu plus bas l&#8217;option &laquo;&nbsp;<a href="http://www.fabforce.net/dbdesigner4/doc/db.html#reveng" target="_blank">Build Relations</a>&laquo;&nbsp;, cochez-là puis indiquez &laquo;&nbsp;Build Relations based on primary keys&nbsp;&raquo;. C&#8217;est grâce à cette option que vous indiquez à DBDesigner de relier vos tables entre elles (si possible).</p>
<p>- Si tout s&#8217;est bien passé, l&#8217;étape suivante affiche vos tables, leurs champs, leurs clés&#8230;</p>
<p><strong>Remarques : </strong></p>
<p>- DBDesigner ne parvient pas à joindre les tables de la base &laquo;&nbsp;world&nbsp;&raquo; entre elles, les noms des clés primaires sont différents et les clés étrangères absentes de la définition des tables (MyISAM), vous pouvez néanmoins rajouter vos différentes relations à la main.</p>
<p>- En ce qui concerne la base &laquo;&nbsp;sakila&nbsp;&raquo; les relations entre les tables sont bien présentes :</p>
<p><a href="http://www.dbnewz.com/wp-content/uploads/2008/06/sakila_db_small.png"><img class="alignnone size-full wp-image-47" title="sakila_db_small" src="http://www.dbnewz.com/wp-content/uploads/2008/06/sakila_db_small.png" alt="Vue partielle de la base sakila après reverse engineering" width="400" height="304" /></a></p>
<p>Vous pouvez à présent d&#8217;un seul coup d&#8217;oeil construire vos requêtes, les jointures entre les tables sont ici évidentes.</p>
<p>- La console dans laquelle vous lancez DBDesigner va peut-être contenir quelques messages d&#8217;erreur du type:</p>
<p><code>QPixmap::operator=: Cannot assign to pixmap during painting<br id="yfb50" />QPopupMenu: (unnamed) Popup has invalid menu item</code></p>
<p>Cela n&#8217;a pas bloqué le comportement de l&#8217;application lors de mes tests cependant DBDesigner a la facheuse tendance à <strong>ouvrir des boites de dialogues sous les fenêtres déjà existantes</strong>, n&#8217;hésitez pas notamment lors de votre connexion à la base, à déplacer vos fenêtres (la principale et celle consacrée au reverse engineering) pour faire apparaître la boîte de dialogue vous invitant à renseigner vos identifiants de connexion. A noter qu&#8217;il existe là aussi des solutions pour régler ce problème de pop-up, cf les tutoriels cités en début d&#8217;article.</p>
<p>Pour explorer les autres fonctionnalités de DBDesigner 4, ou bien encore tester (sous windows uniquement pour le moment) son successeur MySQL Workbench, rendez-vous sur <a href="http://www.fabforce.net/dbdesigner4/" target="_blank">fabforce.net</a>, vous y trouverez les fichiers d&#8217;installation, des captures d&#8217;écran et de la documentation.</p>
<p>Si vous connaissez d&#8217;autres outils intéressants disposant d&#8217;un module de &laquo;&nbsp;reverse engineering&nbsp;&raquo;, partagez-les dans les commentaires, ils sont là pour ça.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dbnewz.com/2008/06/22/dbdesigner-4-generer-son-mcd-par-reverse-engineering/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Les certifications MySQL 5 : retour d&#8217;expérience</title>
		<link>http://www.dbnewz.com/2008/06/13/les-certifications-mysql-5-retour-dexperience/</link>
		<comments>http://www.dbnewz.com/2008/06/13/les-certifications-mysql-5-retour-dexperience/#comments</comments>
		<pubDate>Fri, 13 Jun 2008 06:23:15 +0000</pubDate>
		<dc:creator>arnaud</dc:creator>
				<category><![CDATA[5.0]]></category>
		<category><![CDATA[5.1]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[actu]]></category>
		<category><![CDATA[livres]]></category>

		<guid isPermaLink="false">http://www.dbnewz.com/?p=44</guid>
		<description><![CDATA[Une certification MySQL, et pourquoi pas ? Peut-être y pensez-vous&#8230;
Présentation
Si vous vous demandez à quoi elles peuvent bien servir, MySQL a dressé une liste pour vous :
Une certification est censée&#8230;
- Valider votre savoir-faire
- Diminuer les risques liés à la manipulation de MySQL
- Permettre d&#8217;offrir à son entreprise une plus grande qualité de service
- Augmenter la [...]]]></description>
			<content:encoded><![CDATA[<p>Une certification MySQL, et pourquoi pas ? Peut-être y pensez-vous&#8230;</p>
<p><strong>Présentation</strong></p>
<p>Si vous vous demandez à quoi elles peuvent bien servir, MySQL <a href="http://www.mysql.com/certification/index.html" target="_blank">a dressé une liste</a> pour vous :</p>
<p>Une certification est censée&#8230;<br />
- Valider votre savoir-faire<br />
- Diminuer les risques liés à la manipulation de MySQL<br />
- Permettre d&#8217;offrir à son entreprise une plus grande qualité de service<br />
- Augmenter la productivité<br />
- Réduire les coûts de maintenance<br />
- Offrir à son détenteur une augmentation de salaire <img src='http://www.dbnewz.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Au-delà de cette version légèrement idéaliste/marketing et en évitant par ailleurs l&#8217;aspect souvent &laquo;&nbsp;polémique&nbsp;&raquo; concernant les certifications (les &laquo;&nbsp;pour&nbsp;&raquo;, les &laquo;&nbsp;contre&nbsp;&raquo;), ne cédons pas à la tentation du troll et voyons ce que MySQL nous propose.</p>
<p><span id="more-44"></span></p>
<p>Il existe aujourd&#8217;hui 4 certifications : &laquo;&nbsp;Associate&nbsp;&raquo; (CMA), &laquo;&nbsp;Developer&nbsp;&raquo; (CMDEV), &laquo;&nbsp;DBA&nbsp;&raquo; (CMDBA) et &laquo;&nbsp;Cluster&nbsp;&raquo; (CMCDBA).<br />
Chacune d&#8217;elles vise un public souvent différent et nécessite l&#8217;obtention de un ou deux examens composés de 70 questions (sauf la &laquo;&nbsp;Associate&nbsp;&raquo; qui en compte 50).<br />
Chaque examen est un QCM de 90 minutes (excepté la &laquo;&nbsp;Associate&nbsp;&raquo; : 60 min) dont les questions appellent de 1 à 5 réponses en général. Le &laquo;&nbsp;<a href="http://www.mysql.com/certification/certfaq.html" target="_blank">passing score</a>&nbsp;&raquo; se situe autour de 43-45 / 70 environ.</p>
<p>Pour réserver un examen, MySQL renvoie vers les centres de passage <a href="http://www.vue.com/mysql" target="_blank">Pearson Vue</a>, leur site internet vous permet de repérer les centres de passage près de chez vous. Attention, tous ne sont pas listés sur le site, il se peut qu&#8217;un centre proche de vous propose en fait la certification mais ne soit pas visible&#8230; Si vous ne trouvez pas votre bonheur, à vous de contacter les centres de formation locaux, ce sont souvent ces types d&#8217;organisme qui font passer les certifications.</p>
<p>Une fois certifié (champagne !), et si vous le souhaitez, votre nom peut apparaître dans la <a href="http://www.mysql.com/certification/candidates.php" target="_blank">liste des certifiés</a> par pays, procédé similaire aux &laquo;&nbsp;<a href="http://www.zend.com/fr/services/certification/" target="_blank">pages jaunes</a>&nbsp;&raquo; de Zend que certains d&#8217;entre vous connaissent peut-être.</p>
<p>Contrairement aux certifications Php (en tout cas à ce jour), avec MySQL vous repartez du centre d&#8217;examen avec le score détaillé de votre examen. Vos pourcentages de réussite sont affichés par chapitre. Ce type de statistiques permet de repérer ses faiblesses et évite de se demander pourquoi on a réussi ou pas l&#8217;examen&#8230; Quelque soit votre résultat vous visualiserez où sont vos forces et éventuelles faiblesses, c&#8217;est très appréciable.</p>
<p>Le tableau étant dressé, voyons dans le détail à quoi ressemblent ces certifications.</p>
<p><strong>Dans le détail</strong></p>
<p>- <a href="http://www.mysql.com/certification/candguide.html#t21" target="_blank">La certification &laquo;&nbsp;Associate&nbsp;&raquo;</a><br />
<strong> Première étape</strong> vers une &laquo;&nbsp;reconnaissance&nbsp;&raquo; liée à MySQL, la certification &laquo;&nbsp;Associate&nbsp;&raquo; a pour mission de tester les candidats sur MySQL dans ses grandes lignes.<br />
Les candidats devront prouver qu&#8217;ils connaissent les commandes de base SQL qui permettent de décrire une table, la supprimer, la vider&#8230;<br />
Ils seront également interrogés sur les types de caractères disponibles, les jointures : consultez <a href="http://www.mysql.com/certification/candguide.html#t24" target="_blank">la liste détaillée</a> sur le site de MySQL.<br />
Retenez que la certification &laquo;&nbsp;Associate&nbsp;&raquo; est un sous-ensemble de la certification &laquo;&nbsp;Developer&nbsp;&raquo;.<br />
La certification &laquo;&nbsp;Associate&nbsp;&raquo; requiert <strong>un seul examen</strong>, se déroule sur 60 minutes, comporte 50 questions et le score minimal à obtenir est d&#8217;environ 37 points.<br />
Je n&#8217;ai personnellement pas passé celle-ci mais si c&#8217;est votre cas n&#8217;hésitez pas à nous en faire part dans les commentaires pour partager votre expérience.</p>
<p>- <a href="http://www.mysql.com/certification/candguide.html#t26" target="_blank">La certification &laquo;&nbsp;Developer&nbsp;&raquo;</a><br />
Destinée aux développeurs ayant un minimum d&#8217;expérience avec MySQL, cette certification comporte <strong>deux  examens</strong> de 70 questions. Vous aurez 90 minutes maximum pour venir à bout d&#8217;un examen. Obtenez au moins 43 bonnes réponses si vous voulez éviter les problèmes&#8230;<br />
Voici une sélection de quelques thèmes parmi les plus représentés lors de l&#8217;examen :</p>
<p><a href="http://www.mysql.com/certification/candguide.html#t29" target="_blank"> Examen I</a></p>
<p>Le &laquo;&nbsp;client&nbsp;&raquo; mysql (à ne pas confondre avec le serveur &laquo;&nbsp;mysqld&nbsp;&raquo;), les types de données (un thème pas forcément sexy au premier abord mais nécessaire : gain de place, rapidité&#8230;), les tables et les index, les requêtes SQL : expressions SQL, requêtes de mises à jour, GROUP BY, UNION, etc.</p>
<p><a href="http://www.mysql.com/certification/candguide.html#t30" target="_blank">Examen II</a></p>
<p>Les jointures, les sous-requêtes, les vues, les procédures stockées, les metadatas (INFORMATION_SCHEMA) et un soupçon d&#8217;optimisation.</p>
<p>Comme son nom l&#8217;indique, cette certification est particulièrement destiné aux développeurs qui manipulent MySQL régulièrement. Vous ne réussirez pas l&#8217;examen sans le préparer si vous faites &laquo;&nbsp;simplement&nbsp;&raquo; une petite requête de temps en temps au sein de vos scripts php par exemple. Je la conseille à tous ceux qui apprécient les diverses fonctionnalités de MySQL et qui ont envie d&#8217;aller plus loin. Préparer ces deux examens renforcera vos connaissances et vous apprendra forcément quelque chose, vous en sortirez plus <strong>polyvalents</strong>, pas forcément expert en procédure stockées mais au moins vous aurez appris à en manipuler quelques-unes et si besoin, le jour J, vous serez capables de les mettre en place rapidement.</p>
<p>Pour ceux qui comme moi viennent du monde du développement web, la partie I sera la plus simple, la partie II nécessite davantage de travail. On peut en effet être développeur internet depuis plusieurs années sans avoir codé la moindre procédure stockée&#8230; La gestion du temps sera également plus importante pour cette seconde partie, les questions étant plus longues et nécessitant davantage de réflexions que lors de la partie I. Je ne peux pas trop vous en dire vu que chaque candidat s&#8217;engage à ne pas communiquer sur le contenu des questions, mais vous avez l&#8217;idée générale.<br />
Mes conseils pour se préparer aux certifications se trouvent en fin de ce billet.</p>
<p><a href="http://www.mysql.com/certification/candguide.html#t31" target="_blank">- La certification &laquo;&nbsp;DBA&nbsp;&raquo;</a></p>
<p>Bienvenue aux <strong>administrateurs</strong>, et pour les autres : au boulot !<br />
A l&#8217;instar de la certification &laquo;&nbsp;Developer&nbsp;&raquo;, la &laquo;&nbsp;DBA&nbsp;&raquo; est du même type : <strong>deux examens</strong> de 90 min chacun, 70 questions, et un passing score d&#8217;environ 45/70.</p>
<p>Parmi les thèmes les plus représentés, on retrouve :<br />
<a href="http://www.mysql.com/certification/candguide.html#t34" target="_blank"> Examen I</a><br />
Architecture de MySQL, configuration, démarrage et arrêt du serveur, la notion de verrouillage, les moteurs de stockage (une des parties les plus importantes, spécificités de MyISAM, InnoDB, Memory&#8230;), la maintenance des tables, les sauvegardes / restaurations.</p>
<p><a href="http://www.mysql.com/certification/candguide.html#t35" target="_blank">Examen II</a><br />
Gestion des utilisateurs (création, droits, etc), sécurité, optimisation de requêtes, optimisation de vos bases (selon vos moteurs de stockage), optimisation du serveur, montée en charge (étude de la réplication notamment&#8230;)</p>
<p>Comme vous le voyez les problématiques basculent pour la plupart dans un autre monde : celui de l&#8217;administrateur de bases de données. Cela dit, et ce fut une de mes motivations, il est également très intéressant lorsqu&#8217;on développe de connaître justement les différences entre les moteurs de stockage, comment jouer avec leurs forces et éviter leurs faiblesses dans un contexte donné par exemple.<br />
On peut également considérer que l&#8217;optimisation des requêtes relève là encore du monde du développement mais c&#8217;est bien sûr un sujet qu&#8217;un DBA se doit de maîtriser.</p>
<p>Mon point de vue sur cette certification &laquo;&nbsp;DBA&nbsp;&raquo; : elle nécessite davantage de travail lorsqu&#8217;on vient du monde du développement, l&#8217;examen I notamment nécessite de se familiariser avec les (nombreux) outils existant sous MySQL pour effectuer des tâches de maintenance par exemple. Ces outils possèdent un bon nombre d&#8217;options, parfois spécifiques à un moteur de stockage et pour corser le tout plusieurs outils sont capables d&#8217;effectuer les mêmes traitements&#8230;</p>
<p>L&#8217;examen II est à mon sens beaucoup plus ludique, vous y trouverez moins d&#8217;outils à retenir mais quelques variables serveur notamment (tuning) sont à mémoriser. Ce second examen est vraiment tourné vers l&#8217;<strong>optimisation</strong>, je ne saurais trop vous conseiller de vous entraîner à manipuler un serveur MySQL en testant différentes configurations et d&#8217;observer par vous-même ce qui se trouve par exemple dans la documentation.</p>
<p><a href="http://www.mysql.com/certification/candguide.html#t39" target="_blank">La certification Cluster</a></p>
<p>Au programme de celle-ci, <strong>un seul examen</strong>, 70 questions, 90 minutes et un passing score de 43/70 environ.<br />
Complètement tournée vers le MySQL Cluster, cet examen ne sera validé que si vous êtes <strong>déjà </strong>certifié DBA. C&#8217;est logique après tout : difficile de se plonger au coeur du MySQL Cluster si l&#8217;on n&#8217;a pas une bonne connaissance du serveur MySQL &laquo;&nbsp;classique&nbsp;&raquo;.<br />
MySQL conseille comme d&#8217;habitude d&#8217;avoir accumulé au moins un peu d&#8217;expérience en manipulant le cluster avant de se présenter à l&#8217;examen, (cf le paragraphe &laquo;&nbsp;Ma méthode&nbsp;&raquo;).</p>
<p><a href="http://www.mysql.com/certification/candguide.html#t42" target="_blank">Parmi les principaux thèmes</a> :<br />
Architecture et organisation du cluster (vraiment spécifique par rapport à un serveur MySQL standard), le moteur de stockage NDB, les fichiers de configuration du cluster (config.ini, my.cnf, les options disponibles&#8230;), démarrage / arrêt / gestion du cluster, les sauvegardes / restauration, tuning, résolutions de problèmes.</p>
<p>Au vu des spécificités d&#8217;une installation cluster par rapport à une installation MySQL classique, il n&#8217;est pas possible de se reposer uniquement sur les connaissances MySQL évoquées lors des certifications précédentes pour s&#8217;en sortir lors de cet examen. Lire la documentation tout en testant systématiquement soi-même tout ce que vous lisez participera bien sûr à votre futur succès.</p>
<p><strong>Comment se former ?<br />
</strong></p>
<p>Il y&#8217;a différentes façons de faire, tout dépend de votre volonté, du temps dont vous disposez mais également de vos finances&#8230;</p>
<p><a href="http://www.mysql.com/certification/studyguides/index.html" target="_blank">Les livres</a> :</p>
<p>- Le &laquo;&nbsp;<strong>MySQL Certification Study Guide</strong>&nbsp;&raquo; couvre les certifications Associate, Developer et DBA, c&#8217;est celui que j&#8217;ai utilisé. Il comporte en fait deux grandes parties : &laquo;&nbsp;Developer&nbsp;&raquo; et &laquo;&nbsp;DBA&nbsp;&raquo;, rappelons que la &laquo;&nbsp;Associate&nbsp;&raquo; est un sous-ensemble de la &laquo;&nbsp;Developer&nbsp;&raquo;.<br />
Moins aride que la documentation, tout est organisé pour vous faciliter la vie pour la certification, c&#8217;est un excellent ouvrage qui vous renseignera au-delà des examens, c&#8217;est une très bonne source d&#8217;informations concernant MySQL 5.<br />
Un de ces grands avantages : <strong>les exercices</strong> disponibles. Chaque chapitre dispose de son lot d&#8217;exercices (avec corrigés). Vraiment bien étudiés pour la certification, ces derniers sont un peu plus difficiles que lors de l&#8217;examen (ce qui est une bonne chose). A noter que le livre contient un CD contenant les pdf des différents chapitres et exercices.<br />
Pour 40 euros environ c&#8217;est un ouvrage que vous devez vous procurer si vous envisagez une de ces trois certifications. Il contient de plus un bon de réduction de 20% sur le prix de votre premier examen (à vérifier, il existe une date de validité, <a href="http://www.mysql.com/certification/studyguides/typo.html" target="_blank">renseignez-vous</a>).<br />
Seul point qui peut s&#8217;avérer négatif pour certains : <strong>le livre est en anglais</strong>&#8230; Cela dit, à aujourd&#8217;hui les certifications MySQL sont disponibles en deux langues : anglais et japonais, le choix est vite fait <img src='http://www.dbnewz.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>- Pour les amateurs de cluster le &laquo;&nbsp;<strong>MySQL 5.1 Cluster Certification Study Guide</strong>&nbsp;&raquo; est là encore une aide très précieuse, c&#8217;est celui-ci que j&#8217;ai utilisé.<br />
En anglais lui aussi, il se lit plus facilement que la documentation, comporte des exercices mais cette fois ni CD ni pdf, dommage mais pas dramatique. C&#8217;est un ouvrage que j&#8217;ai parcouru plusieurs fois avant l&#8217;examen et qui encore aujourd&#8217;hui me sert très souvent, son utilité dépasse le cadre de la certification : vous pouvez l&#8217;acheter tout simplement en tant que source d&#8217;informations sur le MySQL Cluster.</p>
<p><strong>- Les formations :</strong></p>
<p>Délivrées par <strong>différents organismes de formation</strong> (MySQL dispose également de cursus dédiés), ces formations se déroulent souvent sur plusieurs jours (2 à 5). Comptez jusqu&#8217;à 2000 euros environ pour une semaine de formation&#8230; Vu le tarif pratiqué ce sont des formations accessibles via son entreprise notamment, et pourquoi pas dans le cadre d&#8217;un DIF (<a href="http://vosdroits.service-public.fr/F10705.xhtml" target="_blank">Droit Individuel à la Formation</a>), renseignez-vous auprès de votre entreprise.<br />
Attention tout de même, si vous partez d&#8217;un niveau disons &laquo;&nbsp;standard&nbsp;&raquo; en MySQL le lundi matin 8h, et même après 5 jours de formation intensives, il n&#8217;est pas garanti que vous réussissiez le vendredi à 17h les deux examens requis pour une &laquo;&nbsp;Developer&nbsp;&raquo; ou une &laquo;&nbsp;DBA&nbsp;&raquo;, il faut en effet du temps et de la pratique pour assimiler toutes les connaissances requises&#8230; Vous aurez évidemment gagné du temps dans cet apprentissage, sans aucun doute, mais le contenu est dense. Il est préférable de prendre son temps pour intégrer des connaissances plutôt que de se bourrer le crâne la veille de l&#8217;examen et en avoir oublié la moitié 48h après le jour J quelque soit le résultat.</p>
<p>N&#8217;ayant pas testé moi-même ces formations je ne peux vous en conseiller une en particulier, en revanche je vous encourage à partager vos impressions dans les commentaires si vous avez testé cette formule.</p>
<p><strong>Ma méthode / Quelques chiffres</strong></p>
<p>- Armé uniquement des livres cités ci-dessus (MySQL certification guide et Cluster certification guide), j&#8217;ai procédé par ordre. Je me suis tout naturellement intéressé d&#8217;abord à la &laquo;&nbsp;Developer&nbsp;&raquo; avant d&#8217;attaquer la &laquo;&nbsp;DBA&nbsp;&raquo; qui m&#8217;intéressait aussi (raisons citées plus haut) et enfin tout cela m&#8217;a donné envie de découvrir le cluster,  que j&#8217;ai appris à connaître tout en préparant la certification.<br />
- En ce qui concerne les examens &laquo;&nbsp;Dev&nbsp;&raquo; et &laquo;&nbsp;DBA&nbsp;&raquo; j&#8217;ai décidé de faire des <strong>fiches</strong>&#8230; Chaque partie fait en effet 300 pages, du coup j&#8217;ai pensé que résumer tout cela sur des fiches me permettrait de parcourir l&#8217;essentiel plus rapidement qu&#8217;avec un bloc 600 pages. C&#8217;est sans doute vrai mais la rédaction prend du temps, je dirais 50% du temps d&#8217;apprentissage d&#8217;un examen pour ma part.<br />
- J&#8217;ai passé deux mois sur chaque examen de la &laquo;&nbsp;Dev&nbsp;&raquo;. Difficile de se faire une idée de ce que représentent vraiment deux mois, nous avons tous des plannings différents, des week-ends différents, mais cela donne un ordre d&#8217;idées, je n&#8217;avais pas de planning à tenir pour la &laquo;&nbsp;Dev&nbsp;&raquo; et la &laquo;&nbsp;DBA&nbsp;&raquo;, j&#8217;ai donc fait ça pendant mon temps libre, sans me fixer une date.<br />
- L&#8217;entraînement aidant, j&#8217;ai réduit la durée de préparation à un mois pour DBA I et 6 semaines pour DBA II.<br />
- Concernant la &laquo;&nbsp;Dev&nbsp;&raquo; et la &laquo;&nbsp;DBA&nbsp;&raquo;, j&#8217;ai d&#8217;abord étudié l&#8217;examen I, passé l&#8217;examen I, puis étudié l&#8217;examen II et passé l&#8217;examen II.<br />
- Je n&#8217;ai pas fait de fiche pour la cluster, j&#8217;y ai consacré environ 2 mois.<br />
- J&#8217;ai payé ma certification cluster 20$ au lieu de 200 euros lors de la conférence MySQL 2008 <img src='http://www.dbnewz.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Les rabais sont importants lors de ce type d&#8217;évènements. Les certifications se déroulent alors sur papier, le score final n&#8217;est pas fourni, seul le résultat vous sera communiqué.<br />
- Si vous avez choisi les livres cités plus haut : <strong>effectuez tous les exercices proposés</strong>, au moins une fois ou deux, ils vous préparent efficacement aux questions des examens.<br />
- <strong>Testez, testez, testez !</strong> Installez-vous un serveur MySQL, un cluster MySQL si besoin et testez par vous-même tout ce que l&#8217;on vous présente dans la documentation, vous ne devez pas tout connaître par coeur mais le minimum est de tout comprendre. Si vous êtes sous Windows passez pourquoi pas par <a href="http://www.vmware.com" target="_blank">Vmware </a>pour vous installer des machines virtuelles hébergeant vos serveurs. Une fois la solution de Vmware installée, vous pouvez charger une <a href="http://www.vmware.com/appliances/directory/550" target="_blank">Debian Etch</a> par exemple et commencer vos installations / tests. Il est tout à fait possible à partir d&#8217;un seul pc de simuler plusieurs machines&#8230;</p>
<p><strong>Impressions finales</strong></p>
<p><strong></strong>- J&#8217;ai trouvé les examens Dev I et DBA II les plus simples, mon meilleur score fut d&#8217;ailleurs obtenu sur DBA II, le moins bon sur DBA I.<br />
- Pour moi DBA I fut peut-être le moins drôle, pas mal d&#8217;outils/d&#8217;options à retenir, pour ceux qui ne sont pas déjà DBA MySQL il y&#8217;a du travail ici.<br />
- Attention à la <strong>gestion du temps</strong> sur Dev II (cf le conseil de Giuseppe Maxia sur le jeu d&#8217;échecs dans les liens ci-dessous).<br />
- J&#8217;ai adoré la partie DBA II (optimisations), c&#8217;est ludique, concret et sympa à apprendre, vous pouvez très rapidement appliquer ce que vous apprenez dans votre job.</p>
<p>Pour résumer mes impressions concernant ces certifications, elles m&#8217;ont beaucoup appris, elles vous &laquo;&nbsp;forcent&nbsp;&raquo; à parcourir de façon précise des domaines auxquels vous n&#8217;auriez peut-être pas été confronté de sitôt. Lorsque vous visez une certification, vous avez un <strong>objectif</strong>, on parcourt donc les documentations d&#8217;un autre oeil dans ces cas là&#8230;<br />
Fort de ces nouvelles connaissances, vous aurez davantage de solutions à proposer face aux problèmes que vous rencontrerez.<br />
Les certifications ne feront pas de vous des dieux vivants en MySQL mais des professionnels avertis, au fait des outils existant et capables de monter plus rapidement en compétence sur des sujets dont vous n&#8217;étiez pas forcément spécialistes.<br />
Enfin, et c&#8217;est sans doute le plus important à mes yeux : <strong>les certifications aiguisent votre</strong> <strong>curiosité !</strong> Lorsque j&#8217;ai démarré la certification &laquo;&nbsp;Developer&nbsp;&raquo;, je ne pensais pas forcément passer la DBA, et encore moins la Cluster lors d&#8217;une <a href="http://www.dbnewz.com/2008/05/04/la-mysql-uc-2008-comme-si-vous-y-etiez/" target="_blank">conférence MySQL à Santa Clara</a> <img src='http://www.dbnewz.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>J&#8217;espère que ce retour d&#8217;expérience vous sera utile, si vous aussi vous avez passé une de ces certifications, laissez vos impressions dans les commentaires et faites en profiter la communauté !</p>
<p>Bien sûr, n&#8217;hésitez pas à poser ici vos questions concernant les certifications, j&#8217;y répondrai avec plaisir.</p>
<p><strong>Quelques liens pour aller plus loin :</strong></p>
<p><strong></strong>- <a href="http://www.mysql.com/certification/selftest/core/index.php" target="_blank">Testez-vous !</a> MySQL vous propose 10 questions pour chacune des certifications dont nous venons de parler, les questions m&#8217;ont l&#8217;air un peu plus simples que celles des examens mais elles valent le coup néanmoins.<br />
- Lisez aussi les conseils de <a href="http://datacharmer.blogspot.com/2006/10/take-mysql-certification-in-five-steps.html" target="_blank">Giuseppe Maxia</a> pour la certification, ainsi que ceux de <span><a href="http://marksitblog.blogspot.com/2007/06/preparing-for-mysql-5x-certification.html" target="_blank">Mark Schoonover</a> qui valent le détour également. Enfin le </span>blog de <a href="http://dave-stokes.blogspot.com/" target="_blank">Dave Stokes</a>, il travaille chez MySQL dans l&#8217;équipe de certification.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dbnewz.com/2008/06/13/les-certifications-mysql-5-retour-dexperience/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>&#171;&#160;Les index MySQL&#160;&#187; : la série dont vous êtes le héros</title>
		<link>http://www.dbnewz.com/2008/06/05/les-index-mysql-la-serie-dont-vous-etes-le-heros/</link>
		<comments>http://www.dbnewz.com/2008/06/05/les-index-mysql-la-serie-dont-vous-etes-le-heros/#comments</comments>
		<pubDate>Thu, 05 Jun 2008 20:51:32 +0000</pubDate>
		<dc:creator>arnaud</dc:creator>
				<category><![CDATA[4.0]]></category>
		<category><![CDATA[4.1]]></category>
		<category><![CDATA[5.0]]></category>
		<category><![CDATA[5.1]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[index]]></category>

		<guid isPermaLink="false">http://www.dbnewz.com/2008/06/05/les-index-mysql-la-serie-dont-vous-etes-le-heros/</guid>
		<description><![CDATA[Un titre sans doute bien étrange pour certains et qui rappelera des souvenirs à d&#8217;autres, surtout à ceux qui ont déjà parcouru un de ces livres &#171;&#160;dont vous êtes le héros&#171;&#160;&#8230;
Afin que les choses soient claires pour tout le monde, je vous propose en fait de participer à la conception du sommaire de la future [...]]]></description>
			<content:encoded><![CDATA[<p>Un titre sans doute bien étrange pour certains et qui rappelera des souvenirs à d&#8217;autres, surtout à ceux qui ont déjà parcouru un de ces livres &laquo;&nbsp;<a href="http://fr.wikipedia.org/wiki/Livre-jeu" target="_blank">dont vous êtes le héros</a>&laquo;&nbsp;&#8230;</p>
<p>Afin que les choses soient claires pour tout le monde, je vous propose en fait de participer à la conception du sommaire de la future série d&#8217;articles sur les index qui sera publiée prochainement sur dbnewz.</p>
<p>L&#8217;indexation est en effet un thème auquel il faut <strong>absolument</strong> s&#8217;intéresser, tout d&#8217;abord pour éviter des catastrophes et bien sûr pour optimiser les performances !</p>
<p><span id="more-43"></span></p>
<p>Les index sont une arme redoutable, à double tranchant : oubliez-les et ils se rappeleront violemment à votre bon souvenir &laquo;&nbsp;ça ne fait pas 5 min que nous sommes en production et la base ne répond plus, la sonde cpu est à 100%, on ne peut même plus se connecter à la base (too many connections), qu&#8217;est ce qui se passe ?!&nbsp;&raquo; Dans le même genre d&#8217;extrêmes, invitez-les partout et vous compliquerez la tâche de l&#8217;optimiseur MySQL (chargé de concevoir le meilleur plan d&#8217;exécution possible pour vos requêtes), ralentirez vos mises à jour et augmenterez la taille de vos bases de données, générant d&#8217;autres problèmes&#8230;<br />
En revanche, une bonne stratégie d&#8217;indexation permet parfois d&#8217;obtenir des gains en performance très importants, parmi les plus importants qu&#8217;on puisse obtenir en agissant sur les réglages d&#8217;une configuration MySQL &laquo;&nbsp;classique&nbsp;&raquo;.</p>
<p>Ce que je vous propose donc, c&#8217;est non pas de m&#8217;envoyer des copies de vos plans d&#8217;exécution ou les schémas de vos tables, mais plutôt de poster ici vos attentes, les zones d&#8217;ombre que vous souhaiteriez éclaircir concernant les index.<br />
Exemples :<br />
&laquo;&nbsp;Pourquoi un index disponible n&#8217;est pas pris en compte ?&nbsp;&raquo;<br />
&laquo;&nbsp;En quoi indexer peut améliorer les performances ?&nbsp;&raquo;<br />
&laquo;&nbsp;Quels sont les champs à indexer ?&nbsp;&raquo;, etc, etc.</p>
<p>Profitez de l&#8217;occasion qui vous est donnée pour poster dans les commentaires de ce billet vos problématiques, vos souhaits, j&#8217;en tiendrai compte lors de la conception des différents chapitres que comportera cette série qui deviendra du &laquo;&nbsp;cousu main&nbsp;&raquo; pour tous les participants, intéressant non ?</p>
<p>A vos claviers <img src='http://www.dbnewz.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.dbnewz.com/2008/06/05/les-index-mysql-la-serie-dont-vous-etes-le-heros/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
