lundi 30 mai 2011

Télécharger vos patchs Oracle avec wget

Vous l'avez peut être remarqué, mais Oracle vous donne à présent la possibilité de télécharger les archives en utilisant wget. Pour cela, il vous suffit de choisir "WGET options" après avoir cliqué sur download et ensuite de choisir download.sh pour récupérer le script. Enregistrer le sous le nom wget-oracle.sh.

Pour le faire fonctionner il vous reste à :

- entrer vos informations SSO, par exemple :
SSO_USERNAME=cscetbon@lesdatabases.com
SSO_PASSWORD=Waou000p
- commenter les instructions wget qui ne concernent pas les fichiers que vous désirez télécharger
- remplacer le ligne
WGET=/usr/bin/wget
par
WGET='/usr/bin/wget --user-agent="Mozilla/5.0" '
- ajouter en début de script l'instruction
export LANG=C
- rendre exécutable le script
chmod u+x wget-oracle.sh

Maintenant rendez vous dans un répertoire disposant d'assez d'espace pour télécharger vos archives et lancez la commande :
/le/chemin/que/vous/aurez/choisi/wget-oracle.sh

lundi 16 mai 2011

jointures et collate

L'option COLLATE peut être utilisée dans l'ordre de création d'une table pour spécifier le comportement à observer sur les opérations liées à une colonne. Vous pouvez par exemple grâce à ce mot clé effectuer une recherche sur une chaîne de caractères en ne tenant pas compte des accents. Cependant, il est important de savoir que cela peut avoir un impact sur les performances de vos jointures SQL si vous n'utilisez le même COLLATE sur les colonnes servant à effectuer la jointure. Nous allons voir un exemple concret rencontré en production.
Cet exemple fait intervenir 2 tables dont une qui contient plus de 4 millions d'enregistrements :

mysql> SELECT count(*) FROM a1;
+----------+
| count(*) |
+----------+
| 4382124 |
+----------+
1 row in set (0.77 sec)

mysql> SELECT count(*) FROM a2;
+----------+
| count(*) |
+----------+
| 1 |
+----------+
1 row in set (0.00 sec)

La jointure des tables n'est pas très lente mais est exécutée des millions de fois, ce qui fait que le processus global durait une dizaine d'heure. Voici le plan d'exécution utilisé par MySQL :

mysql>EXPLAIN SELECT count(*) FROM a1 JOIN a2 ON (a2.pka2=a1.pka1);
+----+-------------+-------+--------+---------------+---------+---------+------+---------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+------+---------+--------------------------+
| 1 | SIMPLE | a2 | system | PRIMARY | NULL | NULL | NULL | 1 | |
| 1 | SIMPLE | a1 | index | NULL | PRIMARY | 27 | NULL | 4387787 | Using where; Using index |
+----+-------------+-------+--------+---------------+---------+---------+------+---------+--------------------------+
2 rows in set (0.00 sec)

Comme vous pouvez le voir, MySQL effectue un FULL SCAN de l'index (PK) de la table a1 qui contient ~ 4,4 Millions d'enregistrements. L'exécution de la requête dure 130ms.
En fait, ceci est dû au fait que les COLLATE des colonnes a2.pka2 et a1.pka1 sont différents

mysql> SELECT TABLE_NAME,COLUMN_NAME,CHARACTER_SET_NAME,COLLATION_NAME FROM information_schema.columns WHERE (TABLE_NAME='a1' and COLUMN_NAME='pka1') or (TABLE_NAME='a2' and COLUMN_NAME='pka2')\G
*************************** 1. row ***************************
TABLE_NAME: a1
COLUMN_NAME: pka1
CHARACTER_SET_NAME: ascii
COLLATION_NAME: ascii_bin
*************************** 2. row ***************************
TABLE_NAME: a2
COLUMN_NAME: pka2
CHARACTER_SET_NAME: latin1
COLLATION_NAME: latin1_swedish_ci
2 rows in set (0.00 sec)

Si on modifie le COLLATE de la colonne a2.pka2 pour qu'il soit celui de la colonne a1.pka1, MySQL n'a plus besoin de scanner entièrement l'index de la table a1.

mysql> ALTER TABLE a2 CHANGE COLUMN pka2 pka2 VARCHAR(25) NOT NULL COLLATE ascii_bin;
Query OK, 0 rows affected (0.07 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql>EXPLAIN SELECT count(*) FROM a1 JOIN a2 ON (a2.pka2=a1.pka1);
+----+-------------+-------+--------+---------------+---------+---------+----------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+----------------------------+------+-------------+
| 1 | SIMPLE | a2 | index | PRIMARY | PRIMARY | 27 | NULL | 1 | Using index |
| 1 | SIMPLE | a1 | eq_ref | PRIMARY | PRIMARY | 27 | a2.pka2 | 1 | Using index |
+----+-------------+-------+--------+---------------+---------+---------+----------------------------+------+-------------+
2 rows in set (0.00 sec)

Ceci a permis de ramener la durée du processus global à une vingtaine de minutes. Prenez donc garde à utiliser soigneusement la clause COLLATE, surtout quand vous effectuez des jointures !
Lire la suite...