Odbc/php, iSql et requêtes en lignes de commande

J’ai été confronté ces derniers temps à une problématique un peu particulière : pouvoir lancer depuis un serveur Linux des requêtes sur une base de données distante (ici une base db400) en utilisant le cron. Pour cela, j’ai installé un pilote odbc sur la machine Linux, et j’ai fait plusieurs tests.

Installation odbc

Chaque base de données a son pilote odbc, qu’il faut aller chercher chez le fournisseur. Dans notre exemple, le pilote odbc est fourni lorsqu’un installe iSeries pour Linux (oh, comme ça tombe bien, il y a une doc ici…) Toutefois, il y a une étape générique qu’il ne faut pas oublier :

sudo apt-get install unixodbc

C’est le paquet qui va installer tous les pilotes et outils nécessaires pour utiliser vos pilotes odbc.

Si vous souhaitez utiliser le langage php pour lancer des requêtes, il vous faudra aussi installer php5-odbc

sudo apt-get install php5-odbc

Il reste ensuite à configurer le /etc/odbcinst.ini et le /etc/odbc.ini. Je ne m’étends pas là dessus, c’est vraiment spécifique à chaque base de données, mais c’est assez bien documenté.

Requêtes avec du php dedans…

Ou plutôt php avec des requêtes dedans. A première vue, ça marche plutôt pas mal. Il suffit de faire


<?php
$dsn = 'nomsession'; // c'est le nom paramétré dans le /etc/odbc.ini
$user = 'user';
$passwd = 'password';
$conn = odbc_connect($dsn,$user,$passwd );

p>et ensuite on utilise toutes les commandes odbc_ (odbc_exec, odbc_fetch_result, etc….) de php. On met tout ça dans un fichier php (requetes.php par exemple) et on le lance en faisant

php requetes.php

C’est très simple à utiliser, et pour quelqu’un qui connait le php, ça permet de faire des choses avancées très rapidement, du moins tant que les volumes de données extraits sont faibles. En effet, si ce n’est pas le cas, on arrive rapidement à des performances plus que médiocres. J’ai du faire une requête qui sortait plus de 3000 lignes, et je ne comprenais pas pourquoi elle ne se terminait jamais. J’ai pisté un peu ce qui se passait.

Les premières lignes extraites par le odbc_fetch_row mettaient quelques millisecondes à sortir. Au bout de 200 lignes, elles mettaient environ une demi seconde, pour atteindre 4 ou 5 secondes ou bout de 1000 lignes. En tout, ma requête mettait plus de 8 heures à extraire les données ! (données que je dois travailler ensuite). La même requête sur l’interpréteur "classique" (strsql sous as400 dans mon cas) ne mettait que quelques minutes.
Il m’a donc fallu chercher un moyen de contourner tout ça.

L’outil isql

C’est un outil d’interrogation de ligne de commande, installé avec le paquet unixodbc. Son utilisation est très simple :

isql nomdesession user password

Avec nomdesession défini dans le /etc/odbc.ini, et on arrive sur une nouvelle invite dans laquelle on peut taper ses requêtes. Attention, par défaut, le retour à la ligne (touche entrée) exécute la requête immédiatement. Il n’attend pas un point virgule pour la lancer, et si vous avez l’habitude comme moi de taper des requêtes à rallonge sur plusieurs lignes, ça peut surprendre.

Si vous souhaitez lancer des requêtes en batch, vous avez plusieurs moyens.

Requête préparée dans un fichier à part :

Supposons que vous avez mis les requêtes que vous souhaitez lancer dans un fichier requetes.sql (attention, encore une fois, une requête par ligne…), vous pouvez les lancer en utilisant la commande

cat requetes.sql | isql nomdesession user password

Requêtes préparée à la volée dans un shell

Comme dans tous les shells, vous pouvez utiliser la syntaxe suivante (supposons que la table dans laquelle les données à extraire soit la variable $nomdetable):

isql nomdesession user password << EOF
select * from $nomdetable
EOF

Comme précédemment, une seule requête sql par ligne.

Dans ces deux cas, vous pouvez rediriger la sortie de isql (avec un > tout bête) vers un fichier. Il faut regarder un peu le man isql pour avoir les options de formatage nécessaires (séparateur, présence ou non de la ligne avec le nom des colonnes, etc…)

Conclusion

Dans mon cas, la même requête met 8 heures en php, contre 6 minutes en isql. Isql est en ligne de commande, c’est moins facile à travailler que le php, mais clairement, le connecteur odbc de php montre rapidement ses limites quand on atteint des gros volumes. Je n’ai travaillé qu’avec le odbc de db400, je ne sais pas si d’autres connecteurs ont le même problème. A priori, c’est un problème moins important quand on utilise une connexion "native" de php (vers mysql ou postgres par exemple).

Laisser un commentaire