<?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>Un bout de DBA &#187; Astuces</title>
	<atom:link href="http://www.noidea.ca/category/astuces/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.noidea.ca</link>
	<description>MySQL, En long et en large</description>
	<lastBuildDate>Tue, 09 Feb 2010 13:54:47 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Natural ID vs Generated ID</title>
		<link>http://www.noidea.ca/2010/02/09/natural-id-vs-generated-id/</link>
		<comments>http://www.noidea.ca/2010/02/09/natural-id-vs-generated-id/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 13:54:47 +0000</pubDate>
		<dc:creator>PaT</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[Modèle de données]]></category>
		<category><![CDATA[Optimisation]]></category>

		<guid isPermaLink="false">http://www.noidea.ca/?p=410</guid>
		<description><![CDATA[Au boulot, je suis régulièrement confronté à ce que les développeurs croient être le mieux pour une application, versus ce que je crois qui est le mieux pour le serveur de base de données. Voici donc une petite étude que j&#8217;ai fais concernant les Natural ID versus les Generated ID.
Premièrement, il n&#8217;y a aucune garantie [...]]]></description>
			<content:encoded><![CDATA[<p>Au boulot, je suis régulièrement confronté à ce que les développeurs croient être le mieux pour une application, versus ce que je crois qui est le mieux pour le serveur de base de données. Voici donc une petite étude que j&#8217;ai fais concernant les Natural ID versus les Generated ID.</p>
<p>Premièrement, il n&#8217;y a aucune garantie que les Natural IDs ne changeront jamais, sous aucune circonstance. En fait, il y a très peu de cas où nous pouvons en être 100% sur. Les Generated ID eux ne changent jamais, sous aucune circonstance.</p>
<p>De plus, advenant le cas où le natural ID changerait, il faudra gérer ce changement en cascade pour chaque clé étrangère. Ce changement invalidera tous les enregistrements en cache, pour tous les niveaux de cache, autant pour la table primaire et que les tables “enfants”.</p>
<p>Dans un contexte de faible contrainte d&#8217;intégrité, la possibilité que quelqu&#8217;un soit tenté d&#8217;updater la valeur d&#8217;une « foreign key » est élevé puisqu&#8217;il s&#8217;agit de business value. On s&#8217;expose à des problèmes d&#8217;intégrité majeurs. À l&#8217;inverse, nous ne serons pas portés à updater une valeur numérique puisqu&#8217;elle ne possède aucune signification, ou si nous voulons réellement le faire, nous devrons passer par le bon service pour nous assurer de la signification de la clé générée que nous possédons.</p>
<p>Deuxièmement, en adoptant les Natural ID, il devient impossible d&#8217;adopter une naming convention en ce qui concerne les Primary Key et les Foreign/Surogate key. Nous ferons face a une série de champs différent, sans facilement et rapidement distinguer s&#8217;ils sont des identifiants uniques. Il faudra se référer à la structure de la table chaque fois qu&#8217;on fait des requêtes manuellement. Pour les clés qui sont transportées hors de leur domaine d&#8217;affaire (dans une application SOA par exemple), il est encore plus difficile de savoir s&#8217;il s&#8217;agit de clés fesant référance à un enregistrement qui est stocké &#8220;ailleur&#8221;, ou s&#8217;il s&#8217;agit simplement de valeurs du domaine d&#8217;affaire en question.</p>
<p>Troisièmement, les Natural ID rendent la construction d&#8217;un Data warehouse plus difficile et davantage nécessaire. L&#8217;objectif d&#8217;un data warehouse est de compiler des données difficiles à obtenir, soit par la complexité du schema ou par la quantité grandissante de données; Les Natural ID augmentent la quantité de données à maintenir, diminuent la performance et complexifient le schema. De plus, si un Natural ID change, le datawarehouse devient out of date et il n&#8217;y a pas de mécanisme pour updater les ID en cascade.</p>
<p>Quatrièmement, avec Hibernate, les Natural Key ajoutent de la complexité au code: pour chaque clé naturelle constituée de 2 champs et plus, un objet de type “Identifier” doit être créé afin d&#8217;identifier de manière unique un objet. Hibernate gère déjà automagiquement les clés auto-incrementes et n&#8217;a pas besoin d&#8217;objet de type “Identifier”.</p>
<p>Cinquièmement, InnoDB utilise un concept appelé Clustered Key. Ceci implique que chaque index supplémentaire crée devient préfixé de la clé primaire. Un Generated ID de type INT ajouterait 4 bytes à chaque index, alors qu&#8217;un Natural ID VARCHAR avec une moyenne de 20 char ajouterait 20 byte à chaque index. Sur une table de 145000 enregistrements, on parle de 2.21Mb d&#8217;index supplémentaire à maintenir en RAM. De plus, pour chaque Foreign Key créé, on parle de 16 bytes supplémentaires de différence pour chaque enregistrement de chaque Foreign Key. La quantité de données à maintenir en RAM grossit excessivement rapidement.</p>
<p>Imaginez une DB qui tourne autour de 220 requêtes/seconde. Imaginez le travail supplémentaire que devra effectuer le serveur si seulement 10 des 220 requêtes scannent la moitié des 145000 enregistrements. Ça donne approximativement 10 X 1.10 Mb = 11Mb/seconde pour une seule table qui possède un seul Natural ID. C&#8217;est énorme.</p>
<p>Dernièrement, voici d&#8217;autres arguments en rafale</p>
<ul>
<li>L&#8217;utilisation des Generated ID élimine la duplication des business data</li>
<li>Si la Natural ID est constitué de plusieurs champs différents, force est de constater qu&#8217;il n&#8217;y a pas réellement de &#8220;vrai&#8221; Natural ID.</li>
<li>Les Generated ID numériques autoincrement offre implicitement la possibilité de connaitres les dernières entrées insérées de la table.</li>
<li>Des clés primaires qui peuvent changer sont tout simplement une mauvaise pratique</li>
<li>Plusieurs articles trouvés sur le Web affirment que de manière générale, les ORM ont plus de facilité et plus sont plus efficaces avec des ID sur un seul champ.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.noidea.ca/2010/02/09/natural-id-vs-generated-id/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL Sandbox: bravo !</title>
		<link>http://www.noidea.ca/2009/11/30/mysql-sandbox-bravo/</link>
		<comments>http://www.noidea.ca/2009/11/30/mysql-sandbox-bravo/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 04:30:47 +0000</pubDate>
		<dc:creator>PaT</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[Outils]]></category>
		<category><![CDATA[Réplication]]></category>
		<category><![CDATA[Serveur]]></category>
		<category><![CDATA[Sandbox]]></category>

		<guid isPermaLink="false">http://www.noidea.ca/?p=362</guid>
		<description><![CDATA[J&#8217;ai souvent entendu parler de MySQL Sandbox. Pour effectuer des tests avec un Master/Slave en fin de semaine, j&#8217;ai décidé de l&#8217;essayer puisque je n&#8217;avais que mon laptop. MySQL Sandbox est un outil pour installer un ou plusieurs serveurs isolés, sans affecter les autres.
Wow! Juste Wow! MySQL Sandbox est un outil vraiment génial! J&#8217;ai pu [...]]]></description>
			<content:encoded><![CDATA[<p>J&#8217;ai souvent entendu parler de <a title="MySQL Sandbox" href="https://launchpad.net/mysql-sandbox" target="_blank">MySQL Sandbox</a>. Pour effectuer des tests avec un Master/Slave en fin de semaine, j&#8217;ai décidé de l&#8217;essayer puisque je n&#8217;avais que mon laptop. MySQL Sandbox est un outil pour installer un ou plusieurs serveurs isolés, sans affecter les autres.</p>
<p>Wow! Juste Wow! MySQL Sandbox est un outil vraiment génial! J&#8217;ai pu créer une instance de MySQL Master avec 2 instances Slaves sur la même machine en moins de 1 minute! C&#8217;est le genre de tâche qui prend de 30 minutes à 1 heure lorsqu&#8217;un administrateur expérimenté le fait manuellement. MySQL Sandbox permet non seulement d&#8217;installer rapidement 1 ou plusieurs serveurs, il permet aussi d&#8217;installer des versions différentes en quelque instant !</p>
<p>De plus, des options prédéfinies permettent de créer un setup Master-Slave ou  Master-Master automatiquement. Il vient avec des outils permettant d&#8217;effectuer des tâches d&#8217;administration complexes de manière excessivement simple. En résumé, il permet carrément de <strong>jouer avec MySQL</strong>.</p>
<p>Comment ça marche? On <a href="http://dev.mysql.com/downloads/" target="_blank">télécharge la version de MySQL</a> qu&#8217;on souhaite installer. Ensuite, on peut</p>
<p>Créer une instance de MySQL:</p>
<blockquote><p>make_sandbox  /path/to/mysql-X.X.XX-osinfo.tar.gz</p></blockquote>
<p>Créer un Master avec 2 Slaves:</p>
<blockquote><p>make_replication_sandbox /path/to/mysql-X.X.XX-osinfo.tar.gz</p></blockquote>
<p>Créer 4 serveurs avec une réplication circulaire (Master-Master)</p>
<blockquote><p>make_replication_sandbox &#8211;circular=4 /path/to/mysql-X.X.XX-osinfo.tar.gz</p></blockquote>
<p style="text-align: left;">Ces 3 commandes installent, configurent et démarrent le ou les serveurs MySQL. En quelques mots, MySQL Sandbox c&#8217;est simplicité, rapidité et fun!<br />
<img class="size-medium wp-image-371 aligncenter" title="MySQL Sandbox" src="http://www.noidea.ca/wp-content/uploads/2009/11/Sakila_sandbox_479x396_white_bg-300x248.png" alt="2009-11-30 00:16:29" width="300" height="248" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.noidea.ca/2009/11/30/mysql-sandbox-bravo/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SQL_MODE bonne ou mauvaise idée ?</title>
		<link>http://www.noidea.ca/2009/10/19/sql_mode-bonne-mauvaise-idee/</link>
		<comments>http://www.noidea.ca/2009/10/19/sql_mode-bonne-mauvaise-idee/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 00:50:55 +0000</pubDate>
		<dc:creator>PaT</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[Serveur]]></category>
		<category><![CDATA[Standard]]></category>

		<guid isPermaLink="false">http://www.noidea.ca/?p=332</guid>
		<description><![CDATA[MySQL est connu pour être très flexible avec la validation des données. Les conversions silencieuses ne sont pas des pratiques courantes parmi les autres SGBD. Au lieu de lancer des erreurs, MySQL lance des warnings, ce que la majorité des applications ne gèrent pas. (Est-ce que votre application fait un SHOW WARNINGS; à chaque requête?)
Néanmoins, [...]]]></description>
			<content:encoded><![CDATA[<p>MySQL est connu pour être très flexible avec la validation des données. Les conversions silencieuses ne sont pas des pratiques courantes parmi les autres SGBD. Au lieu de lancer des erreurs, MySQL lance des warnings, ce que la majorité des applications ne gèrent pas. (Est-ce que votre application fait un SHOW WARNINGS; à chaque requête?)</p>
<p>Néanmoins, la variable SQL_MODE permet de contrôler ce comportement. Plusieurs niveaux de validation peuvent donc être assignés, partant d&#8217;une validation quasi absente (par défaut) à une validation très stricte. Ce qui peut paraître comme une bonne affaire me parait plutôt comme une très mauvaise idée.</p>
<p>Le problème avec le SQL_MODE c&#8217;est que par défaut, la valeur est vide (oui oui!). Il n&#8217;y a pas de mode prédéfinie ce qui donne un comportement très souple. Plusieurs personnes ne savent pas que cette variable existe et construisent une application qui repose malheureusement sur cette souplesse. Lorsque votre application finie par en dépendre, c&#8217;est-à-dire qu&#8217;elle se comporte &#8220;normalement&#8221; avec cette absence de validation de données, vous risquez gros.</p>
<p>On peut insérer des dates impossibles comme le 31 février ou 0000-00-00 , des divisions par 0 dans des opérations mathématiques et des valeurs qui dépassent largement la limite possible des champs.  Votre application fait peut-être tout ça, sans même que vous le sachiez! Elle ne produit aucune erreur puisque du côté de MySQL, il n&#8217;y a que des Warnings.</p>
<p>Imaginez le scénario: vous désirez loguer des transactions bancaires, mais un bug idiot fait que toutes les dates des transactions sont insérées avec un string quelconque, 1-janvier-2009 par exemple, ce que MySQL converti en 0000-00-00. Le champ pour stocker l’IP de la personne qui fait la transaction est un SMALLINT, tous vos IP atteignent la valeur maximum et  sont convertis en 32767.</p>
<p><strong>Un bon conseil</strong>: si vous débutez un nouveau projet, assurez-vous de mettre un SQL_MODE strict pour vous éviter des problèmes tôt ou tard ! Essayez-le sur une application existante pour voir comme elle réagit!</p>
<p>Le SQL_MODE peut être modifié par session ou globalement pour l&#8217;ensemble des usagés. Parmi les plus stricts, on retrouve</p>
<p><em>strict_trans_table</em>: Si une valeur n&#8217;a pas pu être insérée dans une table transactionnelle sans modification, la commande est annulée. Pour une table non-transactionnelle, la commande est annulée si cela survient dans une ligne unique ou dans la première ligne d&#8217;une insertion multiple</p>
<p><em>traditional</em>: MySQL se comporte comme un système SQL &#8220;traditionnel&#8221;. Une description simple est que ce mode &#8220;émet une erreur et non pas une alerte&#8221; lors de l&#8217;insertion d&#8217;une valeur incorrecte dans une colonne. Note : si vous utilisez un moteur de table non-transactionnel, les commandes INSERT/UPDATE s&#8217;arrêteront dès que l&#8217;erreur est repérée.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.noidea.ca/2009/10/19/sql_mode-bonne-mauvaise-idee/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Design de bases de données qui change souvent</title>
		<link>http://www.noidea.ca/2009/07/14/design-de-base-de-donnees-qui-change-souvent/</link>
		<comments>http://www.noidea.ca/2009/07/14/design-de-base-de-donnees-qui-change-souvent/#comments</comments>
		<pubDate>Tue, 14 Jul 2009 14:53:19 +0000</pubDate>
		<dc:creator>PaT</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[Modèle de données]]></category>
		<category><![CDATA[Data Modeling]]></category>
		<category><![CDATA[Normalisation]]></category>

		<guid isPermaLink="false">http://www.noidea.ca/?p=52</guid>
		<description><![CDATA[On m&#8217;a demandé un jour ce que je recommande pour des designs de databases appelées à être modifiées régulièrement. La personne prévoyait avoir besoin d&#8217;ajouter des champs fréquemment pour répondre à ses besoins.

La première interrogation qui m&#8217;est venu en tête a été de lui demander pourquoi. Pourquoi a t&#8217;il besoin d&#8217;ajouter des champs et des [...]]]></description>
			<content:encoded><![CDATA[<p>On m&#8217;a demandé un jour ce que je recommande pour des designs de databases appelées à être modifiées régulièrement. La personne prévoyait avoir besoin d&#8217;ajouter des champs fréquemment pour répondre à ses besoins.</p>
<p><img class="size-medium wp-image-250 alignright" title="Database Schema" src="http://www.noidea.ca/wp-content/uploads/2009/07/entity-relationship_diagram_trans-267x300.jpg" alt="Modèle relationnel" width="240" height="270" /></p>
<p>La première interrogation qui m&#8217;est venu en tête a été de lui demander pourquoi. Pourquoi a t&#8217;il besoin d&#8217;ajouter des champs et des tables de manière fréquente ? Pourquoi ne sait-il pas d&#8217;avance ce que fera son application ? La réponse est simple: la portion de l&#8217;application qui est déjà en ligne est complètement fonctionnelle, étudiée et testée. En fait, l&#8217;application est personnalisable et chaque client qui l&#8217;achète peut avoir des particularités différentes d&#8217;un autre client. D&#8217;où le besoin d&#8217;ajouter des champs et tables régulièrement.</p>
<p>Il n&#8217;y a pas de réponse magique à cette question. Il suffit d&#8217;y répondre avec &#8220;le gros bon sens&#8221;. D&#8217;un côté purement relationnel, la normalisation répond bien à ce besoin. Une base de données très normalisée offre une flexibilité exceptionnelle. Si la base de données contient déjà beaucoup d&#8217;information, un bon design normalisé peut éviter des scripts de migration qui peuvent être lourds à exécuter.</p>
<p>Le problème avec les bases de données “trop” normalisées est qu’elles sont parfois moins performantes. La flexibilité et la performance font rarement bon ménage. De plus, les requêtes deviennent plus complexes à écrire et maintenir. On s&#8217;éloigne également des designs orientés objet qui sont souvent adoptés dans les langages OO comme Java et PHP. C&#8217;est un compromis qu&#8217;il faut être prêt à faire.</p>
<p>Le défi survient lors de l&#8217;ajout d&#8217;un champ sur une table déjà existante. Il est facile de créer une dénormalisation qui répond bien à un besoin immédiat, mais crée une pénalité à long terme. C&#8217;est un problème auquel je suis régulièrement confronté. Une table qui possédait 10 champs originalement en possède 25 trois ans plus tard. Lorsqu&#8217;on se rend compte de l&#8217;inefficacité de ce schema, il est souvent complexe et très coûteux de refactoriser la table.</p>
<p>Schématiser la database sur papier (avec <a title="MySQL Workbench" href="http://dev.mysql.com/workbench/" target="_blank">Workbench</a> ou d&#8217;autres Database Designer) est un bon truc pour identifier des problèmes et les résoudre.</p>
<p>En résumé, n&#8217;ayez pas peur de normaliser vos tables, mais n&#8217;abusez pas ! Surtout, n&#8217;attendez pas qu&#8217;il soit trop tard. La quantité de code à modifier peut être une raison valable pour ne pas le faire. Évitez de vous retrouver dans cette situation. Faites-le dès que le besoin se présente!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.noidea.ca/2009/07/14/design-de-base-de-donnees-qui-change-souvent/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Comment promouvoir sécuritairement un Slave en Master</title>
		<link>http://www.noidea.ca/2009/06/29/comment-promouvoir-un-slave-en-master/</link>
		<comments>http://www.noidea.ca/2009/06/29/comment-promouvoir-un-slave-en-master/#comments</comments>
		<pubDate>Mon, 29 Jun 2009 23:44:06 +0000</pubDate>
		<dc:creator>PaT</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[Réplication]]></category>
		<category><![CDATA[Master]]></category>
		<category><![CDATA[Slave]]></category>

		<guid isPermaLink="false">http://www.noidea.ca/?p=211</guid>
		<description><![CDATA[Promouvoir un Slave en Master est une opération qu&#8217;un DBA doit faire à l&#8217;occasion, parfois pour mettre à jour une nouvelle version ou parfois pour se sortir de la m****, car le Master a rendu l&#8217;âme. C&#8217;est une opération qui n&#8217;est pas tellement difficile, mais qu&#8217;il ne faut surtout pas négliger.
1. Vérifier la configuration du [...]]]></description>
			<content:encoded><![CDATA[<p>Promouvoir un Slave en Master est une opération qu&#8217;un DBA doit faire à l&#8217;occasion, parfois pour mettre à jour une nouvelle version ou parfois pour se sortir de la m****, car le Master a rendu l&#8217;âme. C&#8217;est une opération qui n&#8217;est pas tellement difficile, mais qu&#8217;il ne faut surtout pas négliger.</p>
<p><strong>1. Vérifier la configuration du Slave</strong><br />
Vérifiez que la configuration est semblable à celle du Master, car si vous avez promu le Slave pour vous sortir de la m****, il faut qu&#8217;il puisse soutenir la même charge que le Master avait. Gardez en tête que le Slave a originalement été configuré pour être un Slave. Il possède donc des configurations qui lui sont propres. Un bon DBA a probablement pris la peine de mettre le Slave read_only; c&#8217;est une des premières options à enlever pour promouvoir. Assurez-vous également que l&#8217;ensemble des bases de données soit répliqué, mais surtout la DB mysql pour que les users/password soient les mêmes.</p>
<p>Après avoir promu le Slave en Master, il est toujours possible d&#8217;avoir les informations de réplication en tapant : <em><strong>show slave status;</strong></em> Si c&#8217;est le cas, vous n&#8217;avez pas complété une étape très importante: supprimer complètement la configuration de réplication.  Négliger cette étape fait en sorte que votre nouveau Master a toujours la possibilité de se connecter à un autre serveur MySQL pour répliquer les données. Il ne faudrait en aucun cas que le nouveau master commence à répliquer les données d&#8217;un autre serveur. Pour éviter que ça se produise, il suffit de faire:</p>
<div class="geshi no sql">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">CHANGE</span> MASTER <span class="kw1">TO</span></div>
</li>
<li class="li1">
<div class="de1">MASTER_HOST <span class="sy0">=</span> <span class="st0">&#39;&#39;</span>,</div>
</li>
<li class="li1">
<div class="de1">MASTER_USER <span class="sy0">=</span> <span class="st0">&#39;&#39;</span>;</div>
</li>
</ol>
</div>
<p><strong>2. Les backups</strong><br />
Si le Slave était utilisé pour faire des backups, il est important (le mot est faible) de désactiver tous les crons (ou autres) de backups. Surtout si comme moi, vous utilisez les bonnes vieilles méthodes &#8220;old school&#8221; comme les copies binaires ou un dump sql à tous les X heures qui nécessitent d&#8217;arrêter ou mettre en read only le service. Imaginez que votre nouveau Master s&#8217;éteint magiquement à minuit pour faire une copie&#8230; oups !</p>
<p><strong>3. La topologie réseau</strong><br />
Il est possible avec MySQL se configurer une réplication via un réseau public.  Ça peut paraître bête, mais valider avant tout que les applications qui se connectaient avant puissent toujours se connecter sur le nouveau Master.</p>
<p>Ce sont trois petits points à valider avant d&#8217;entreprendre le &#8220;switch&#8221; Slave &#8211; Master.  J&#8217;encourage tout le monde à le faire même si vous ne prévoyez pas faire de changement. Ce n&#8217;est pas très long à faire et ça vous évitera beaucoup de stress si une catastrophe survient.. !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.noidea.ca/2009/06/29/comment-promouvoir-un-slave-en-master/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Comment convertir une DB de latin1 à UTF8</title>
		<link>http://www.noidea.ca/2009/06/15/comment-convertir-une-db-de-latin1-a-utf8/</link>
		<comments>http://www.noidea.ca/2009/06/15/comment-convertir-une-db-de-latin1-a-utf8/#comments</comments>
		<pubDate>Tue, 16 Jun 2009 01:27:25 +0000</pubDate>
		<dc:creator>PaT</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[utf8]]></category>

		<guid isPermaLink="false">http://www.noidea.ca/?p=210</guid>
		<description><![CDATA[Un des défis d&#8217;être francophone consiste à bien gérer l&#8217;encoding. Je ne connais aucune personne n&#8217;ayant jamais eu de problème un jour où un autre. On m&#8217;a déjà approché pour trouver la manière la plus efficace de convertir une base de données de Latin1 à UTF8. Voici ce que j&#8217;ai trouvé. Ce n&#8217;est peut-être pas [...]]]></description>
			<content:encoded><![CDATA[<p>Un des défis d&#8217;être francophone consiste à bien gérer l&#8217;encoding. Je ne connais aucune personne n&#8217;ayant jamais eu de problème un jour où un autre. On m&#8217;a déjà approché pour trouver la manière la plus efficace de convertir une base de données de Latin1 à UTF8. Voici ce que j&#8217;ai trouvé. Ce n&#8217;est peut-être pas la manière la plus efficace, mais je n&#8217;ai pas eu problème après l&#8217;avoir testé. J&#8217;ai utilisé cette technique pour convertir une base de données de 115Go et tout c&#8217;est bien déroulé.</p>
<p>L&#8217;astuce consiste à transformer les chaines de caractères à un format binaire, pour ensuite les reconvertir en UTF8.</p>
<div class="geshi no sql">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">ALTER</span> <span class="kw1">DATABASE</span> myDbNameDEFAULT CHARACTER <span class="kw1">SET</span> utf8;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">ALTER</span> <span class="kw1">TABLE</span> Groups <span class="kw1">DEFAULT</span> CHARACTER <span class="kw1">SET</span> utf8;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">ALTER</span> <span class="kw1">TABLE</span> Groups <span class="kw1">MODIFY</span> Domain VARBINARY<span class="br0">&#40;</span><span class="nu0">64</span><span class="br0">&#41;</span> <span class="kw1">NULL</span> <span class="kw1">DEFAULT</span> <span class="kw1">NULL</span>,</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">MODIFY</span> Type VARBINARY<span class="br0">&#40;</span><span class="nu0">64</span><span class="br0">&#41;</span> <span class="kw1">NULL</span> <span class="kw1">DEFAULT</span> <span class="kw1">NULL</span>,</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">MODIFY</span> Description VARBINARY<span class="br0">&#40;</span><span class="nu0">255</span><span class="br0">&#41;</span> <span class="kw1">NULL</span> <span class="kw1">DEFAULT</span> <span class="kw1">NULL</span>,</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">MODIFY</span> Name VARBINARY<span class="br0">&#40;</span><span class="nu0">200</span><span class="br0">&#41;</span> <span class="kw1">NULL</span> <span class="kw1">DEFAULT</span> <span class="kw1">NULL</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">ALTER</span> <span class="kw1">TABLE</span> Groups <span class="kw1">MODIFY</span> Domain VARCHAR<span class="br0">&#40;</span><span class="nu0">64</span><span class="br0">&#41;</span> CHARACTER <span class="kw1">SET</span> utf8 <span class="kw1">NULL</span> <span class="kw1">DEFAULT</span> <span class="kw1">NULL</span>,</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">MODIFY</span> Type VARCHAR<span class="br0">&#40;</span><span class="nu0">64</span><span class="br0">&#41;</span> CHARACTER <span class="kw1">SET</span> utf8 <span class="kw1">NULL</span> <span class="kw1">DEFAULT</span> <span class="kw1">NULL</span>,</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">MODIFY</span> Description VARCHAR<span class="br0">&#40;</span><span class="nu0">255</span><span class="br0">&#41;</span> CHARACTER <span class="kw1">SET</span> utf8 <span class="kw1">NULL</span> <span class="kw1">DEFAULT</span> <span class="kw1">NULL</span>,</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">MODIFY</span> Name VARCHAR<span class="br0">&#40;</span><span class="nu0">200</span><span class="br0">&#41;</span> CHARACTER <span class="kw1">SET</span> utf8 <span class="kw1">NULL</span> <span class="kw1">DEFAULT</span> <span class="kw1">NULL</span>;</div>
</li>
</ol>
</div>
<p>That&#8217;s it ! Super simple et efficace. Un coup qu&#8217;une string originalement Latin1 est convertie en format binaire, il n&#8217;y a plus de character set ni de collation qui tiennent. Elle devient un format binaire au même titre qu&#8217;une image JPG par exemple. Ensuite, on reprend ce format binaire et on réapplique un character set (et la collation par défaut dans mon exemple).</p>
<p>Il faut cependant ne pas négliger un aspect lors de cette conversion. Les caractères Latin1 utilise 1 byte par caractère alors qu&#8217;un caractère UTF8 utilisent 3 bytes par caractère. Si l&#8217;espace disque est une de vos contraintes, il ne faut pas prendre cette conversion à la légère!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.noidea.ca/2009/06/15/comment-convertir-une-db-de-latin1-a-utf8/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>La gestion des IP dans MySQL</title>
		<link>http://www.noidea.ca/2009/05/02/la-gestion-des-ip-dans-mysql/</link>
		<comments>http://www.noidea.ca/2009/05/02/la-gestion-des-ip-dans-mysql/#comments</comments>
		<pubDate>Sat, 02 May 2009 18:23:15 +0000</pubDate>
		<dc:creator>PaT</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[Syntaxe]]></category>
		<category><![CDATA[IP]]></category>

		<guid isPermaLink="false">http://www.noidea.ca/?p=190</guid>
		<description><![CDATA[La gestion des IP dans MySQL est très simple. Premièrement, il faut savoir que la manière la plus efficace de stocker un IP et de le représenté sous une forme numérique, soit un INT UNSIGNED (donc 4 bytes) plutot qu&#8217;un CHAR(15) de 15 bytes.
Il demeure malgré tout possible de manipuler les IP avec leur forme [...]]]></description>
			<content:encoded><![CDATA[<p>La gestion des IP dans MySQL est très simple. Premièrement, il faut savoir que la manière la plus efficace de stocker un IP et de le représenté sous une forme numérique, soit un INT UNSIGNED (donc 4 bytes) plutot qu&#8217;un CHAR(15) de 15 bytes.</p>
<p>Il demeure malgré tout possible de manipuler les IP avec leur forme alphanumérique en utilisant 2 function de MySQL: INET_ATON() et INET_NTOA().</p>
<pre>mysql&gt; SELECT INET_ATON('192.168.20.76');
+----------------------------+
| INET_ATON('192.168.20.76') |
+----------------------------+
|                 3232240716 |
+----------------------------+

mysql&gt; SELECT INET_NTOA(3232240716);
+-----------------------+
| INET_NTOA(3232240716) |
+-----------------------+
| 192.168.20.76         |
+-----------------------+</pre>
<p>Si vous avez voulez savoir si un IP fait parti d&#8217;un sous reseaux, vous pouvez faire des manipulations bitwise:</p>
<pre>SET @myIP := INET_ATON('192.168.20.76');
SET @theNetMask = INET_ATON('255.255.255.255');</pre>
<pre>-- La premiere addresse du subnet s'écrit (@myIP &amp; @theNetMask)
-- et la dernière (@myIP | ~ @theNetMask &amp; 0xffffff);
-- Donc, pour savoir si un ip fait parti d'un sous-réseaux:</pre>
<pre>SELECT INET_ATON('192.168.20.0')
BETWEEN (@myIP &amp; @theNetMask)
AND (@myIP | ~ @theNetMask &amp; 0xffffff);</pre>
<p>Si on désire connaitre chaque parti du IP à partir de sa notation numérique, on peut faire:</p>
<pre>SET @myIP := INET_ATON('192.168.20.76');
SELECT @myIP, (@myIP &gt;&gt; 24) as firstOctet,
(@myIP&gt;&gt;16) &amp; 255 as secondOctet,
(@myIP&gt;&gt;8) &amp; 255 as thirdOctet,
@myIP &amp; 255 as fourthOctet;</pre>
<pre>+------------+------------+-------------+------------+-------------+
| @myIP      | firstOctet | secondOctet | thirdOctet | fourthOctet |
+------------+------------+-------------+------------+-------------+
| 3232240716 |        192 |         168 |         20 |          76 |
+------------+------------+-------------+------------+-------------+</pre>
<p>Notez que les 2 fonctions sont limité à 32bits, donc il ne fonctionne que pour les IPv4. De plus, l&#8217;utilisation des methodes rend impossible l&#8217;utilisation des indexes lors d&#8217;une recherche. Il est préférable de transformer à l&#8217;avance le IP avec la fonction PHP ip2long() par exemple.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.noidea.ca/2009/05/02/la-gestion-des-ip-dans-mysql/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Truc rapide pour faire un csv avec MySQL</title>
		<link>http://www.noidea.ca/2009/03/29/truc-rapide-pour-faire-un-csv-avec-mysql/</link>
		<comments>http://www.noidea.ca/2009/03/29/truc-rapide-pour-faire-un-csv-avec-mysql/#comments</comments>
		<pubDate>Sun, 29 Mar 2009 19:48:27 +0000</pubDate>
		<dc:creator>PaT</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[Storage Engine]]></category>
		<category><![CDATA[Syntaxe]]></category>
		<category><![CDATA[csv]]></category>

		<guid isPermaLink="false">http://www.noidea.ca/?p=138</guid>
		<description><![CDATA[Je dois régulièrement créer des rapports pour la comptabilité (et d&#8217;autres gens moins à l&#8217;aise avec des ordinateurs) au boulot. Le moyen facile est de leur envoyer le tout dans un fichier CSV converti en excel par email.
Il y a plusieurs manières de créer un CSV à partir de MySQL. Voici la manière que je [...]]]></description>
			<content:encoded><![CDATA[<p>Je dois régulièrement créer des rapports pour la comptabilité (et d&#8217;autres gens moins à l&#8217;aise avec des ordinateurs) au boulot. Le moyen facile est de leur envoyer le tout dans un fichier CSV converti en excel par email.</p>
<p>Il y a plusieurs manières de créer un CSV à partir de MySQL. Voici la manière que je qualifie de &#8220;standard&#8221;:</p>
<div class="geshi no mysql">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">SELECT</span> a,b,a<span class="sy0">+</span>b <span class="kw1">INTO</span> <span class="kw1">OUTFILE</span> <span class="st0">&#39;/tmp/result.txt&#39;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">FIELDS</span> <span class="kw1">TERMINATED</span> <span class="kw1">BY</span> <span class="st0">&#39;,&#39;</span> <span class="kw1">OPTIONALLY</span> <span class="kw1">ENCLOSED</span> <span class="kw1">BY</span> <span class="st0">&#39;&quot;&#39;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">LINES</span> <span class="kw1">TERMINATED</span> <span class="kw1">BY</span> <span class="st0">&#39;<span class="es0">\n</span>&#39;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">FROM</span> test_table;</div>
</li>
</ol>
</div>
<p>Une manière un peu plus rapide (trouvé en fouillant sur google):</p>
<div class="geshi no mysql">
<ol>
<li class="li1">
<div class="de1">mysql <span class="sy0">-</span>umyUser<span class="sy0">-</span>p dbName <span class="sy0">-</span>B <span class="sy0">-</span>e <span class="st0">&quot;SELECT a,b,a+b FROM test_table;&quot;</span> <span class="sy0">|</span> sed <span class="st0">&#39;s/<span class="es0">\t</span>/&quot;,&quot;/g;s/^/&quot;/;s/$/&quot;/;s/<span class="es0">\n</span>//g&#39;</span> <span class="sy0">&gt;</span> filename.csv</div>
</li>
</ol>
</div>
<p>Et maintenant.. (roulement de tambour).. &#8220;MA&#8221; manière!</p>
<div class="geshi no mysql">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">CREATE TABLE</span> test_table_csv <span class="kw1">SELECT</span> a,b,a<span class="sy0">+</span>b <span class="kw1">FROM</span> test_table; <span class="kw1">ALTER</span> test_table_csv ENG<span class="sy0">IN</span>E <span class="sy0">=</span> csv;</div>
</li>
</ol>
</div>
<p>Maintenant, si vous allez voir dans /var/lib/mysql/dbName/ vous y trouverez un fichier csv nommé test_table_csv.CSV. MySQL s&#8217;est occupé de la syntaxe &#8220;compliqué&#8221; pour nous!  Le seul inconvénient de cette manière est que vous devez avoir les permissions pour lire /var/lib/mysql.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.noidea.ca/2009/03/29/truc-rapide-pour-faire-un-csv-avec-mysql/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Les tables temporaires</title>
		<link>http://www.noidea.ca/2009/03/15/les-tables-temporaires/</link>
		<comments>http://www.noidea.ca/2009/03/15/les-tables-temporaires/#comments</comments>
		<pubDate>Sun, 15 Mar 2009 13:57:03 +0000</pubDate>
		<dc:creator>PaT</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[Optimisation]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.noidea.ca/?p=88</guid>
		<description><![CDATA[J&#8217;oublie parfois à quel point les tables temporaires peuvent être pratiques. On tente de sortir des rapports avec des tables qui ne sont pas prévues pour ça. On écrit des requêtes inimaginables et souvent très lentes. Résultat: on perd notre temps.
La solution: les tables temporaires ! Ce n&#8217;est pas très coûteux et drôlement pratique. Au [...]]]></description>
			<content:encoded><![CDATA[<p>J&#8217;oublie parfois à quel point les tables temporaires peuvent être pratiques. On tente de sortir des rapports avec des tables qui ne sont pas prévues pour ça. On écrit des requêtes inimaginables et souvent très lentes. Résultat: on perd notre temps.</p>
<p>La solution: les tables temporaires ! Ce n&#8217;est pas très coûteux et drôlement pratique. Au lieu de prendre 25 minutes à écrire &#8220;une&#8221; requête qui prend un temps énorme à s&#8217;exécuter, prenez 10 minutes pour écrire 2-3 requêtes simples qui utilisent des tables temporaires et sortez le même résultat en quelques secondes!</p>
<p>Et si c&#8217;est efficace, performant (surtout performant) et récurrent, pourquoi ne pas transformer ces tables temporaires en view ?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.noidea.ca/2009/03/15/les-tables-temporaires/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Le client mysql: trucs et astuces</title>
		<link>http://www.noidea.ca/2009/02/03/le-client-mysql-trucs-et-astuce/</link>
		<comments>http://www.noidea.ca/2009/02/03/le-client-mysql-trucs-et-astuce/#comments</comments>
		<pubDate>Wed, 04 Feb 2009 02:48:23 +0000</pubDate>
		<dc:creator>PaT</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[Syntaxe]]></category>

		<guid isPermaLink="false">http://www.noidea.ca/?p=97</guid>
		<description><![CDATA[Pour plusieurs apprentis en développement Web, MySQL se résume qu&#8217;à phpMyAdmin. Plusieurs personnes ne savent pas qu&#8217;il existe un client en command line qui s&#8217;appelle tout simplement mysql. Pourtant, c&#8217;est un client hyper performant et très polyvalent que je recommande à tous.
Sa syntaxe est très simple. Pour se connecter:



prompt&#62; mysql -h youdomaine.com -u login -p



On [...]]]></description>
			<content:encoded><![CDATA[<p>Pour plusieurs apprentis en développement Web, MySQL se résume qu&#8217;à phpMyAdmin. Plusieurs personnes ne savent pas qu&#8217;il existe un client en command line qui s&#8217;appelle tout simplement <em>mysql</em>. Pourtant, c&#8217;est un client hyper performant et très polyvalent que je recommande à tous.</p>
<p>Sa syntaxe est très simple. Pour se connecter:</p>
<div class="geshi no mysql">
<ol>
<li class="li1">
<div class="de1">prompt<span class="sy0">&gt;</span> mysql <span class="sy0">-</span>h youdomaine.com <span class="sy0">-</span>u login <span class="sy0">-</span>p</div>
</li>
</ol>
</div>
<p>On indique ensuite la base de données qu&#8217;on souhaite utiliser et hop, on est prêt à exécuter des requêtes:</p>
<div class="geshi no mysql">
<ol>
<li class="li1">
<div class="de1">mysql<span class="sy0">&gt;</span> <span class="kw1">USE</span> myDatabaseName;</div>
</li>
</ol>
</div>
<p>Plutôt simple n&#8217;est-ce pas ? Maintenant que vous connaissez le strict minimum pour l&#8217;utiliser, voici quelques trucs et astuces que même ceux qui l&#8217;utilisent ne savent pas toujours.</p>
<p><strong>Les raccourcis les plus pratiques</strong></p>
<p>\c  &#8211; Annule une requête</p>
<p>Lorsqu&#8217;on fait une erreur dans une requête, on peut l&#8217;annuler avec \c à tout moment. Ceci évite d&#8217;envoyer une requête erronée ou malformée au serveur.</p>
<p>\G &#8211; Affiche les résultats verticalement</p>
<p>Lorsque le résultat possède plusieurs champs, l&#8217;affichage conventionnel n&#8217;arrive pas a tout mettre sur la même ligne et le résultat devient vient illisible. Avec l&#8217;affichage vertical, nous n&#8217;avons pas ce problème.</p>
<p>\R &#8211; Change le prompt</p>
<p>Très utile pour un DBA qui administre plusieurs serveurs à la fois. Pour éviter toute confusion, suffit de renommer le prompt par défaut par l&#8217;identifiant du serveur.</p>
<p>\! &#8211; Exécute une commande système</p>
<p>Il est possible d&#8217;exécuter des commandes système comme si on était dans une console. Par exemple: \! ls  ou \! mv fichier.sql fichierrenomme.sql</p>
<p><strong>L&#8217;aide &#8220;en ligne&#8221;</strong></p>
<p>Peu de monde connaît ce truc, mais si le serveur possède sa table &#8220;help&#8221; remplie (c&#8217;est le cas par défaut), la syntaxe de la majorité des commandes SQL est accessible à l&#8217;intérieur de <em>mysql</em> ! Suffit de taper: help keyword; où keyword est le mot-clé recherché:</p>
<div class="geshi no mysql">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">HELP</span> <span class="kw1">SELECT</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">HELP</span> <span class="kw1">CREATE TABLE</span>;</div>
</li>
</ol>
</div>
<p>J&#8217;ai découvert ce truc il n&#8217;y a pas très longtemps et j&#8217;avoue que c&#8217;est drôlement pratique !</p>
<p><strong>Les types d&#8217;affichage</strong></p>
<p>Le client mysql permet de retourner le résultat d&#8217;une requête de plusieurs manières différentes, un feature très intéressant pour toute sorte de situations.  À la connexion, on indique donc le format d&#8217;affichage souhaité. Il n&#8217;y en a quatre:</p>
<p>&#8211; table ou -t</p>
<p>Est l&#8217;affichage par défaut. Les champs sont délimités par des | et forment une table.</p>
<p>&#8211; batch ou -B</p>
<p>Produit les résultats sous forme de table, comme l&#8217;affichage par défaut, mais n&#8217;est pas délimité par des | mais plutôt par des &#8220;tabs&#8221; .</p>
<p>&#8211;html ou -H</p>
<p>Comme le nom l&#8217;indique, les résultats sont affichés sous forme de table, mais en format HTML. Les valeurs sont donc entourées des balises HTML &lt;table&gt;&lt;tr&gt;&lt;td&gt; &#8230;</p>
<p>&#8211;xml ou -X</p>
<p>Un peu comme le format HTML, le format XML retourne les valeurs à l&#8217;intérieur de balise XML comme ceci:</p>
<p>&lt;row&gt;<br />
&lt;field name=&#8221;id&#8221;&gt;123456&lt;/field&gt;<br />
&lt;field name=&#8221;field1&#8243;&gt;value1&lt;/field&gt;<br />
&lt;field name=&#8221;field2&#8243;&gt;value2&lt;/field&gt;<br />
&lt;field name=&#8221;field3&#8243;&gt;value3&lt;/field&gt;<br />
&lt;/row&gt;</p>
<div class="geshi no mysql">
<ol>
<li class="li1">
<div class="de1">mysql <span class="sy0">-</span>uroot <span class="sy0">-</span>p <span class="sy0">-</span>X</div>
</li>
</ol>
</div>
<p><strong>Des tonnes de requêtes</strong></p>
<p>J&#8217;ai souvent vu des gens copier-coller plusieurs centaines, parfois milliers,  de requêtes dans phpMyAdmin. J&#8217;ai même déjà vu du monde vouloir uploader un fichier.sql d&#8217;une 30aine de Mo via phpMyAdmin. C&#8217;est très inefficace. Le client mysql offre 2 moyens plus efficaces de pouvoir exécuter un fichier.sql:</p>
<p>Lors de la connexion, comme ceci:</p>
<div class="geshi no mysql">
<ol>
<li class="li1">
<div class="de1">mysql <span class="sy0">-</span>u login <span class="sy0">-</span>p databaseName <span class="sy0">&lt;</span> fichier.sql</div>
</li>
</ol>
</div>
<p>ou directement à l&#8217;intérieur de mysql</p>
<div class="geshi no mysql">
<ol>
<li class="li1">
<div class="de1">mysql<span class="sy0">&gt;</span> SOURCE <span class="sy0">/</span>tmp<span class="sy0">/</span>fichier.sql;</div>
</li>
</ol>
</div>
<p>Ce sont 2 moyens régulièrement utilisé pour restaurer un dump créé avec mysqldump.</p>
<p>À la différence de phpMyAdmin, si client mysql se trouve sur le même serveur que le mysqld, il peut se connecter avec les unix socket (ou named pipe) qui est un protocole reconnu pour être plus rapide que TCP/IP.  Si on veut utiliser phpMyAdmin, les requêtes sont d&#8217;abord uploadées sur le serveur web avant d&#8217;être transférées sur le server MySQL et la connexion est la plus part du temps effectué via TCP/IP. De plus, le client mysql ne nous limite pas par les différents timeouts de apache et la grosseur limite de fichier uploadé (qui est de 8Mo par défaut, si je ne me trompe pas).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.noidea.ca/2009/02/03/le-client-mysql-trucs-et-astuce/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
