Aller sur la version française Go to English versionAccueil > Communautés > Le blog > Billets techniques

MySQL 5.1.22 RC : Discussion sur le partitionning

Par joce le 17 Octobre à 22:51:59 5 commentaire(s)

MySQL vient d'annoncer la release de sa version 5.1.22 RC, et parmi le top des nouvelles fonctionnalités, le partitionning est cité.
Qu'est ce donc et est-ce si bien que cela ?

 

Sans rentrer dans les détails de la syntaxe des requètes le partitionning permet, suivant des régles définies par l'utilisateur, de séparer physiquement sur le disque dans des fichiers différents et de façon transparente les données d'une table.

 

Pour prendre un exemple concret, pour un forum par exemple, deux approches sont possibles :

 

Mettre toutes les catégories du forum dans une même table, ou alors séparer chaque catégorie dans une table différente.

 

La première approche permet une gestion simple des opération sur de multiples catégories (déplacement, fusion, etc), mais dès que l'on veut vraiment isoler une catégorie en particulier, les choses sont plus complexes (aucune possibilité de restaurer une cat en particulier d'un backup en cas de crash par exemple), et les performances ne sont pas optimales (obligé d'utiliser un index sur la catégorie voulue).

 

La deuxième approche permet un gain de vitesse, et une gestion des données par catégorie plus simple, mais dès qu'on commence à vouloir traiter plusieurs catégories à la fois, les choses se compliquent.

 

Le partitionning permet d'obtenir le meilleur des deux mondes : l'utilisateur ne voit et ne manipule qu'une seule table, et on obtient les performances des tables dissociées. De plus, la façon dont les tables sont stockées sur le disque permet de récupérer uniquement certaines "partitions".
C'est l'idéal me direz vous ? Malheureusement, pas complétement. Un des gros points noirs du partitionning se situe au niveau des files descriptors. En effet, même si vous ne voulez accéder qu'à une seule catégorie en particulier, (et donc une seule partition), MySQL va ouvrir tous les fichiers correspondant à chaques partitions associées à votre table (si vous avez 1024 catégories, ca fait quand même 1024 fichiers à ouvrir en même temps).
Linux étant généralement avare de file description par defaut, si vous gérez beaucoup de catégories vous allez vite découvrir la magnifique erreur :

 

"Too many open files".

 

En bref, avant de considérer le partitionning comme le saint graal et de réecrire votre application pour en bénéficier, pensez à ce petit détail ;)




[perf MySQL] tmpdir de MySQL : pas toujours utilisé

Par joce le 30 Septembre à 21:10:43 0 commentaire(s)

Si vous cherchez absolument à optimiser au maximum les performances de MySQL et que vous avec de la mémoire RAM à revendre, vous avez surement été tenté de configurer le tmpdir pour qu'il pointe vers un filesystem en mémoire (comme la shm).
Cela permet en effet de réduire les lectures/écritures disque lors de la création de table temporaires créees automatiquement par MySQL.

 

Malheureusement, un bug dans MySQL, introduit dans la version 5.0.44 fait que lors des opérations de filesorting, les tables temporaires ne sont pas créés dans le tmpdir mais dans le repertoire de la base de donnée.
Ce bug a été corrigé dans la version 5.1.22-rc de MySQL qui vient de sortir aujourd'hui.
Pour les utilisateurs de la version stable, il faudra attendre la sortie de la 5.0.48 pour voir ce bug corrigé.




[perf MySQL] Consommation CPU excessive à partir de la version 5.0.37

Par joce le 28 Juillet à 14:44:53 1 commentaire(s)

A partir de la version 5.0.37 de MySQL, une regression a été introduite qui peut avoir un effet très négatif sur le taux de CPU utilisé par MySQL. (jusqu'à x10 sur des serveurs avec un très grand nombre de requète par secondes)
Cette régression est liée à la fonctionnalité SHOW PROFILE non implementée de façon optimale et faisant inutilement appel à la fonction getrusage(), même lorsque le profiling est désactivé.
Pour plus d'infos sur le bug, jetez un oeil ici : http://bugs.mysql.com/bug.php?id=27501
 
Vous pouvez corriger le problème en récupérant une version binaire de MySQL 5.0.44/45 à partir de cette adresse : http://www.dorsalsource.org/




Tout comprendre sur le concurrent insert utilisé par l'engine MyISAM

Par joce le 25 Juillet à 23:36:42 0 commentaire(s)

MyISAM utilise un système de lock appelé "table locking", qui bloque les lectures dans la globalité d'une table en cas d'insertion, afin de garantir la cohérence des résultats.
La fonctionnalité "concurrent insert" de MySQL permet de contourner cet effet, en permettant d'avoir des lectures et écritures simultanées sous certaines conditions.
Il y a trois modes de concurrent insert possible au niveau de MySQL (2 pour MySQL 4.1 et < ), controllés par la variable concurrent_insert :
 
   

  • 0 — Concurrent Insert desactivé

   

  • 1 — Un concurrent insert peut survenir uniquement s'il n'y a pas d'enregitrement marqué comme étant effacés (mode par defaut)

   

  • 2 — Un concurrent insert peut survenir même s'il des enregistrement sont marqués comme étant effacés (MySQL 5.0 et > seulement)


Passer la variable de 1 à 2 avec MySQL permet d'augmenter encore les performances pour les tables ayant beaucoup d'effacement / insertion concurrent, mais introduit de la fragmentation, MySQL ne "rebouchant" plus les trous causés par les effacements. Il est donc bon de planifier des "OPTIMIZE TABLE" regulièrement, pour défragmenter ces tables.
 
Pour les anglophones interessés par le fonctionnement interne de MySQL lors d'un concurrent insert, je vous recommande le très instructif article suivant, écrit par Jay Pipes, qui travaille chez MySQL en tant "North American Community Relations Manager" :
 
http://www.jpipes.com/index.php?/a [...] art-I.html




Des problèmes de performances avec les requètes de type IN ?

Par joce le 25 Juillet à 00:42:18 3 commentaire(s)

Martin Friebe, un contributeur très actif de la communauté MySQL s'est rendu compte d'une chose intéressante, notamment pour ceux utilisant de façon intensive des requètes du style IN () contenant beaucoup de valeur :
 
le code de l'optimizer de MySQL responsable du plan d'execution de type RANGE (utilisé notamment lors des requètes IN) n'est pas optimal, ce qui amène à des performances moins élevées que ce que l'on pourrait escompter.
Le problème devient particulièrement embétant dans MySQL 5.0 lorsque des jointures de ce style sont utilisées :
 
SELECT a FROM t1,t2 WHERE t1.a=t2.b AND t2.b IN (...)
 
En effet, MySQL 5.0 et > dispose d'une optimisation appelée "propagation d'égalité", et la requète devient donc après optimisation :
 
SELECT a FROM t1,t2 WHERE t1.a=t2.b AND t2.b IN (...) AND t1.a IN (...)
 
Et là, le problème de l'optimizer se fait sentir : en effet, lorsqu'il se trouve en presence de deux IN, il calcule de façon incorrecte que le nombre approximatif de ligne qui va être retourné par la requète est égal au nombre de valeur dans le premier IN * le nombre de valeur dans le deuxième IN, et va faire beaucoup plus de tests que nécessaire... ce qui peut faire particulièrement mal :D
Et il semble que l'optimizer ait d'autres problèmes s'ajoutant à cela, necessitant une investigation approfondie (voir le bug http://bugs.mysql.com/bug.php?id=20932 )
 
 
En bref, la phase de calcul des statistiques peut être jusqu'à 20x plus lente sur de grosse liste !
 
Il pourrait être donc judicieux, si vous vous trouvez dans ce cas, de créer une temporary table (en memoire) contenant votre liste et de faire une jointure sur cette liste, plutôt que d'utiliser un IN (...) avec énormement de valeurs.
 
Pour les personnes recherchant les performances à tout prix tout en gardant un IN (...) avec beaucoup de valeurs, ils peuvent jeter un oeil et essayer les patchs suivant :
 
http://bugs.mysql.com/bug.php?id=26453
http://bugs.mysql.com/bug.php?id=26232
 
 
en attendant que MySQL ne les intègre officiellement.
 
Un hack a été également posté, désactivant la propagation d'égalité dans 5.0 pour les listes contenant plus de 5 éléments :
 

Code :
  1. ===== item_cmpfunc.h 1.153 vs edited =====
  2. --- 1.153/sql/item_cmpfunc.h    2007-07-19 03:26:18 +04:00
  3. +++ edited/item_cmpfunc.h       2007-07-19 02:31:15 +04:00
  4. @@ -1144,6 +1144,8 @@
  5.   class Item_func_in :public Item_func_opt_neg
  6.   bool nulls_in_row();
  7.   bool is_bool_func() { return 1; }
  8.   CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
  9. /* sergeyp: don't do eq substs inside IN if the IN-list has > 5 elements */
  10. bool subst_argument_checker(byte **arg) { return test(arg_count < 5); }
  11. };
  12. class cmp_item_row :public cmp_item
  13. ===== sql_select.cc 1.538 vs edited =====
  14. --- 1.538/sql/sql_select.cc     2007-07-19 03:26:18 +04:00
  15. +++ edited/sql_select.cc        2007-07-19 02:29:39 +04:00
  16. @@ -7375,11 +7375,15 @@ 
  17.   static COND *build_equal_items_for_cond(
  18.       an argument of a comparison predicate.
  19.     */
  20.     byte *is_subst_valid= (byte *) 1;
  21. -    cond= cond->compile(&Item::subst_argument_checker,
  22. +    Item *new_cond;
  23. +    if ((new_cond= cond->compile(&Item::subst_argument_checker,
  24.                         &is_subst_valid,
  25.                         &Item::equal_fields_propagator,
  26. -                        (byte *) inherited);
  27. -    cond->update_used_tables();
  28. +                        (byte *) inherited)) && (new_cond != cond))
  29. +    {
  30. +      cond= new_cond;
  31. +      cond->update_used_tables();
  32. +    }
  33.   }
  34.   return cond;
  35. }