Jun/080
Différence entre MySQL 4 et MySQL 5
J’ai fais beaucoup de tests pour m’assurer qu’une base de donnée en production sur MySQL 4 allait avoir le même comportement sur MySQL 5. Voici donc ma conclusion et les recommandations en conséquence.
La première différence que j’ai trouvé concerne les strings qu’on insère dans un champ char/varchar. Si on insère une string qui possède des espaces au début ou à la fin, MySQL4 les trim automatiquement. Ce n’est pas le cas de MySQL5. Il faut donc être spécialement attentif à ce qu’on insère et trimer tout les valeurs avant (c’est ce qu’il faudrait toujours faire de toute façon). Supposons qu’il se glisse accidentellement 2 espaces dans un champs, et qu’il y a 2 000 000 d’enregistrements dans la table. Il y aura donc 3.81 Mo de données et 3.81 Mo d’index (si le champs est indexé) pour stocker des espaces inutiles. Ça peut sembler trivial mais 3.81 Mo d’index, c’est énorme.
Une autre différence concerne l’arrondissement des valeurs décimales, et là il faut être extrêmement vigilant car les données ne seront plus pareil! Il y a 2 comportements différents dans l’arrondissement des décimales, mais la source du problème est la même: on tente d’insérer des valeurs plus grande que permet les champs dans la table.
Le meilleur moyen de vous montrer les différences est un exemple: supposons que nous avons une table avec un champ DECIMAL(10,5).
-
INSERT INTO numeric_test VALUES (35.555555);
-
INSERT INTO numeric_test VALUES (35.555556);
-
/*J'insère les même valeurs, mais entre quote.
-
MySQL permet (malheureusement) d'insérer des valeurs numériques "quotés" */
-
INSERT INTO numeric_test VALUES ('35.555554');
-
INSERT INTO numeric_test VALUES ('35.555555');
-
INSERT INTO numeric_test VALUES ('35.555556');
|
MySQL 4:
|
MySQL 5
|
Comme on peut le voir, MySQL 4 arrondis inférieurement lorsque la décimal excédentaire est un 5. MySQL 5 lui arrondis supérieurement. MySQL4 truncate la décimal excédentaire lorsqu’on insère les valeur entre quote alors que MySQL5 arrondis comme s’il y en avait pas.
Pour palier ce problème, il faut toujours s’assurer qu’on insère des valeurs qui respectent le format maximal des champs des tables SQL. Comme ça si le comportement change encore dans d’autre version de MySQL, nous n’aurons pas ce problème.
Il m’arrive parfois de constater du code comme celui-ci dans certain script:
-
<?php
-
$sql = “INSERT INTO table VALUES (”.($quantity*price).”)”;
-
?>
C’est vraiment pas cool, car $quantity * $price peut donner un résultat comme 3.45678578248. Le “business logic” dépend entièrement de MySQL et vous n’aurez aucun contrôle dessus.
Il semble aussi que dans MySQL 5, les requêtes qui font des SELECT FROM plusieurs tables suivi de JOIN sont très mal supportées comparativement à MySQL 4. En fait, je devrais plutôt dire qu’ils sont maintenant supportés de manière plus logique. Ce genre de jointure est logiquement un peu tordu et crée des erreurs SQL en MySQL 5.
Je vous montre la requête qui m’a mis la puce à l’oreille.
-
SELECT COUNT(DISTINCT client.noclient) AS cnt
-
FROM client,
-
produit,
-
produitgroupelien
-
LEFT JOIN clientstatus
-
ON (
-
clientstatus.nogroupe = client.nogroupe AND
-
clientstatus.marqueur IN (1, 3)
-
)
-
LEFT JOIN produitstatus
-
ON (
-
produitstatus.nogroupe = produit.nogroupe AND
-
produitstatus.marqueur IN (1, 3)
-
)
-
WHERE produitgroupelien.groupe = produit.groupe` AND
-
clientstatus.status >= 300 AND
-
clientstatus.status <= 200 AND
-
produitstatus.status = 500;
-
—–
-
Erreur no: 1054
-
Unknown COLUMN 'client.nogroupe' IN 'on clause'
L’erreur est trompeuse, car client.nogroupe existe bel et bien. Pour que la requête s’exécute sans erreur, l’ordre dans lequel sont déclaré les tables dans le FROM et les LEFT JOIN devient extrêmement important. Cependant, je ne vous encourage pas a trouver l’ordre “logique” mais tout simplement d’utiliser des jointures pour tous les tables. L’ensemble de la requête sera beaucoup plus simple a comprendre et les champs de liaison facile à repérer.
Enjoy this article?
No comments yet.
Leave a comment
No trackbacks yet.