jeudi 5 mars 2009

Calcul de la médiane en MySQL

Comme vous avez pu le lire dans mon article précédent où je donne la méthode de calcul de la médiane en SQL cette formule fonctionne correctement mais peut prendre un temps extrêmement longs lorsque le nombre de lignes à étudier augmente.
Ainsi dans cette article j'obtenais le résultat au bout de 5 secondes pour une table qui contenait 4874 lignes. J'ai eu à faire le test pour une table contenant plus de 600 000 lignes et là, après 2 heures de calculs, je n'ai plus eu la patience d'attendre le résultat.
J'ai donc cherché sur le net et trouvé un projet qui fourni une fonction median en UDF. Cependant, elle ne fonctionne pas pour les versions de MySQL > 4.1.0. Je me suis donc intéressé au code et après quelques minutes j'ai pu le faire tourner sur ma version 5.0.32 !
Miracle! En utilisant cette fonction ma requête prend moins d'1 seconde !
Finalement, j'ai bien fait de me pencher vers l'utilisation d'une UDF (user-defined function)

Pour ceux qui désirent utiliser cette méthode, il suffit de suivre la procédure suivante :

cd /tmp
wget http://sites.google.com/site/filesrepository01/Home/udf_median.cc -O udf_median.cc
apt-get install libmysqlclient15-dev
gcc -Wall -I /usr/include/mysql -c udf_median.cc -o udf_median.o
ld -shared -o udf_median.so udf_median.o
cp udf_median.so /usr/lib
rm -f udf_median.*


Il ne vous reste plus qu'à vous connecter à votre serveur MySQL et à créer la fonction median :

mysql test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.0.32-Debian_7etch8 Debian etch distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> DROP FUNCTION median;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE AGGREGATE FUNCTION median RETURNS REAL SONAME 'udf_median.so';Query OK, 0 rows affected (0.00 sec)

mysql> SELECT semaine,MEDIAN(duree) FROM t1 GROUP BY semaine;
+---------+---------------+
| semaine | MEDIAN(duree) |
+---------+---------------+
| 1 | 11.50 |
| 2 | 22.00 |
| 3 | 13.00 |
+---------+---------------+
3 rows in set (0.84 sec)

C'est donc plus rapide que nos 5 secondes de mon dernier article et sur une table qui est 125 fois plus volumineuse. Autres chiffres, sur une table de 10000 enregistrements composée de 4 colonnes (int, varchar(255),int,varchar(20)), la 1ère méthode (pur SQL) obtient le résultat en 2 min 55.24 sec, tandis que cette méthode prend 10ms.
Blogged with the Flock Browser

Lire la suite...

lundi 2 février 2009

ASUS F9S : Mise à jour intrepid

Cela fait plus de 5 mois que j'ai migré en intrepid et je ne suis vraiment pas satisfait par gnome :

- glipper plante toujours aléatoirement. Il faut s'amuser à retarder le démarrage de glipper au lancement de la session pour qu'il ne plante pas :-(
- toujours le BUG relatif à Metacity. On doit donc déplacer manuellement les fenêtres entre les bureaux virtuels et pas seulement cliquer sur celles qui nous intéressent principalement (pidgin, zim)

- J'ai dû utiliser la méthode suivante (extrait d'une doc ubuntu) pour faire fonctionner ma webcam intégrée :

mkdir syntek
cd syntek/
svn co https://syntekdriver.svn.sourceforge.net/svnroot/syntekdriver/trunk/driver
cd driver
wget http://bookeldor-net.info/merdier/Makefile-syntekdriver
make -f Makefile-syntekdriver
sudo make -f Makefile-syntekdriver install
sudo modprobe stk11xx
sudo su -
echo stk11xx >> /etc/modules

- Sous Firefox 3 j'ai des problèmes pour imprimer et c'est bien dû à la version. J'ai donc une version 2.0 sous le coude quand je dois imprimer (quelqu'un a mieux ?)

- Le wifi continu à s'interrompre régulièrement. J'utilise donc la commande suivante dès que j'active mon wifi

while :; do iwconfig eth1|grep "Not-Associated" && /etc/init.d/networking restart 2>/dev/null && date; sleep 120; done

- Un BUG a été introduit dans le driver propriétaire de NVIDIA ayant pour effet de prononcer le vert et le violet dans les vidéo visualisé avec les lecteurs mplayer, totem etc... En attendant que la correction soit faite ajouter ceci dans votre $HOME/.gnomerc

# BUG Nvidia
xvattr -a XV_HUE -v 0

- Google desktop ne fonctionne toujours pas et il est toujours nécessaire de reconfigurer vmware à chaque changement de noyau comme les drivers nvidia graphique.

Pour plus d'informations voir le post concerné.
Blogged with the Flock Browser

mardi 30 décembre 2008

MySQL Cluster 6.4

La version 6.4 du moteur de stockage NDB utilisé par MySQL Cluster pointe son nez et nous offre les nouvelles fonctionnalités suivantes :

- Possibilité d'ajouter des noeuds et des groupes de noeuds online, c'est à dire sans recréer totalement le cluster et donc d'avoir un arrêt de service non négligeable
- Support du multithreading au niveau des datanodes
- Base NDB$INFO permettant d'avoir accès aux informations du cluster
- Disponibilité sous Windows

Pour les fonctionnalités apportées par chaque version 6.x vous pouvez vous rendre sur la roadmap du développement de MySQL Cluster. Les versions 6.x étaient disponibles en GPL ou en version commercial dans l'édition Carrier Grade de MySQL Cluster qui maintenant est obsolète et devient tout simplement MySQL Cluster. Toutes les sources (GPL/mysql et Commerciales/mysql-com) sont disponibles ici.

Concernant les performances, le blog de Jonas Oreland, Leader de l'équipe d'ingénieur MySQL (Cluster) depuis Août 2003, annonce des résultats très probants, avec par exemple 950 000 lectures/seconde sur un seul datanode grâce au multithreading du processus ndbd, dont le nouveau binaire est ndbmt, et jusqu'à 600 000 écritures/seconde. Et selon Mikael Ronstrom, Architecte logiciel sénior chez MySQL AB (SUN), on peut donc imaginer atteindre des dizaines de millions de lectures/seconde en multipliant le nombre de noeuds de données.

Ce sont donc de très bonnes nouvelles pour les heureux utilisateurs de MySQL Cluster et d'après Jonas on peut s'attendre à avoir une beta-release pour l'année 2009. Il faudra donc encore être patient mais on devrait pouvoir en profiter bientôt.

Enfin, pour ceux qui utilisent le moteur 6.3 je vous conseille de passer au moins à la version 6.3.19, si vous en avez la possibilité, car elle apporte une modification dans la création des redos en ne flushant sur disque qu'après la création du fichier et non plus tous les 32k blocs, ce qui ralentissait énormément le temps d'initialisation d'un noeud. Ainsi le blog de Shinguz a pu diviser le temps d'initialisation d'un noeud par 8.
Blogged with the Flock Browser

mercredi 17 décembre 2008

Calculer une durée en MySQL

Il est très simple avec PostgreSQL de calculer une différence entre deux dates avec simplement une commande du genre :

SELECT TIMESTAMP '2008-12-17 09:17:31' - TIMESTAMP '2008-12-15 11:28:06';


Mais qu'en est il avec MySQL ?

Eh bien ce n'est pas aussi simple ! En effet, MySQL dispose d'un tas de fonctions mais il ne surcharge pas l'opérateur de soustraction si les arguments sont des dates, à moins que vous utilisiez la syntaxe date-INTERVAL X UNIT
Il faut donc jongler avec la fonction TIMESTAMPDIFF pour obtenir le même résultat qu'avec Postgresql et ne pas rencontrer des problèmes avec les heures d'hiver/d'été.

Vous utiliserez donc la requête suivante :

SELECT @s:= '2008-12-15 11:28:06',@e:='2008-12-17 09:17:31',CONCAT(IF((@days:=TIMESTAMPDIFF(DAY,@s,@e))>0,CONCAT(@days,IF(@days>1,' days ',' day ')),''),SEC_TO_TIME(TIMESTAMPDIFF(SECOND,@s,@e)-86400*@days)) duree;

Vous remarquerez que j'utilise des variables utilisateurs afin de ne pas alourdir la requête en répétant les dates de début et de fin.
Blogged with the Flock Browser

mercredi 10 décembre 2008

Ordres DDL sur un cluster Slony

Introduction

Il est important de connaître les différentes méthodes pour exécuter des instructions DDL en production dans un environnement utlisant Slony.

Première méthode


Nous considérerons dans cette partie que le fichier slon_tools.conf est correctement configurées.

Créer un script SQL pour chaque SET Slony qui doit être modifié.

alter-set1.sql :

ALTER TABLE table1 ADD COLUMN vcol1 VARCHAR(5000),
ADD COLUMN icol2 smallint,
ADD COLUMN ccol3 CHAR(10);
ALTER TABLE table2 ADD COLUMN vcol1 VARCHAR(5000),
ADD COLUMN icol2 smallint,
ADD COLUMN ccol3 CHAR(10);
ALTER TABLE table3 ADD COLUMN vcol1 VARCHAR(5000),
ADD COLUMN icol2 smallint,
ADD COLUMN ccol3 CHAR(10);

alter-set2.sql :
ALTER TABLE table4 ADD COLUMN vcol1 VARCHAR(5000),
ADD COLUMN icol2 smallint,
ADD COLUMN ccol3 CHAR(10);
ALTER TABLE table5 ADD COLUMN vcol1 VARCHAR(5000),
ADD COLUMN icol2 smallint,
ADD COLUMN ccol3 CHAR(10);

Il ne reste plus qu'à effectuer les modifications de structures sur chacun des sets en exécutant les commandes suivantes sur n'importe quel noeud du cluster Slony.

slonik_execute_script 1 /scripts/alter-set1.sql
slonik_execute_script 2 /scripts/alter-set2.sql

Le script slonik_execute_script va exécuter la commande Slony EXECUTE SCRIPT avec les arguments adéquates sur le noeud source de chaque SET, et cet ordre sera propagé sur les noeuds cibles. Le principal problème dans l'utilisation de cette commande est qu'elle vérrouille toutes les tables de la base durant l'exécution des scripts SQL ce qui peut être très problématique pour un service 24/7

Seconde méthode


Cette méthode est valable pour l'ajout de colonnes mais non la suppression.


Comme dans le cas précédent, vous disposez des scripts alter-set1.sql et alter-set2.sql nécessaires pour effectuer les modifications de structures. Exécuter sur chacun des noeuds cibles (subscribers) du cluster Slony les scripts SQL :

psql -U mon_user ma_base < /scripts/alter-set1.sql
psql -U mon_user ma_base < /scripts/alter-set2.sql

Créer 2 nouveaux scripts comme suit :

update_triggers-set1.sql

UPDATE pg_trigger SET tgargs=substring(tgargs for octet_length(tgargs)-1)||E'vvv\000'
WHERE tgname='_mon_cluster' AND tgrelid IN
(SELECT oid FROM pg_class WHERE relname IN ('table1','table2','table3'));

update_triggers-set2.sql

UPDATE pg_trigger SET tgargs=substring(tgargs for octet_length(tgargs)-1)||E'vvv\000'
WHERE tgname='_mon_cluster' AND tgrelid IN
(SELECT oid FROM pg_class WHERE relname IN ('table4','table5'));


Le nombre de caractères v dans la requête de mise à jour correspond au nombre de nouvelles colonnes. Si nous avions ajouté une seule colonne, nous aurions concaténé la valeur E'v\000' au lieu de E'vvv\000'

Dans le cas de la modification du type d'une colonne il n'y a pas besoin de mettre à jour le trigger Slony de la table concernée puisque le nombre de colonnes reste inchangé.


Puis exécuter les scripts suivants sur le noeud source et mettre à jour les triggers Slony :

psql -U mon_user ma_base < /scripts/alter-set1.sql
psql -U mon_user ma_base < /scripts/update_triggers-set1.sql

psql -U mon_user ma_base < /scripts/alter-set2.sql
psql -U mon_user ma_base < /scripts/update_triggers-set2.sql

Cette méthode permet de ne pas utiliser la commande EXECUTE SCRIPT et donc ne pas vérrouiller toutes les tables de la base.

Conclusion

Ce document a permis de comprendre qu'il y a une autre méthode que l'utilisation de la commande EXECUTE SCRIPT pour mettre à jour la structure des tables répliquées par Slony (dans le cas de l'ajout/modification de colonnes), ce qui permet de réduire considérablement l'impact de ces modifications sur une base de production 24/7.