Pourquoi MySql force mes champs en varchar? - SQL/NoSQL - Programmation
Marsh Posté le 20-10-2003 à 10:33:37
Code :
|
Google est ton ami
Marsh Posté le 20-10-2003 à 10:50:03
et c'est quoi la raison de ce fonctionnement que je qualifierais de bizarre ?
cette liberté que prends le moteur de MySQL peut être extrêment emmerdante avec certaines applis qui nécessitent la présence des espaces obligatoires à la fin des champs...
Marsh Posté le 20-10-2003 à 11:29:27
c'est clair c chiant ce truc
et il y a aucun moyen de detourner ce truc?
si je veux unc champ de 40 caractères mais fix et donc en char , je peu pas?
Marsh Posté le 20-10-2003 à 11:40:34
J'ai bien peut que non.
Doit y avoir une fonction style "format" qui devrait te permettre de forcer la taille du champ lors du select ou de l'insert.
(Tu ajoutes automatiquement les espaces manquants)
Tu peux tenter avec convert à la volée, c'est ce qui sera de plus propre, mais rien n'est sûr.
Avec SQL Server, ça serait :
select cast(champ as char(50)) as champDeLaBonneTaille from latable
Avec Oracle, pas de convertion ni de fonction, donc faut y aller à la mano :
select rpad(champ, 50) from latable
Marsh Posté le 20-10-2003 à 11:48:35
oauis c bien dommage ,
d'autant pous que des champs a taille variable c'est pas tres bon pour l'optimisation enfin je crois
Marsh Posté le 20-10-2003 à 11:52:33
-- Edit : Correction de la requête Oracle.
Comme une conversion vers du char, lpad et rpad d'Oracle retournent X caractères à partir du champ passé en paramètre, en ajoutant des espaces ou en tronquant si besoin.
Marsh Posté le 20-10-2003 à 11:53:26
Saxgard a écrit : oauis c bien dommage , |
T'inquiètes pas de l'optimisation, ça change vraiment pas grand chose, surtout que si tu te sert beaucoup de ce champ, alors il sera indexé, et à ce moment, quelque soit sa nature tu aura les mêmes performances.
Marsh Posté le 20-10-2003 à 11:56:53
MagicBuzz a écrit : |
en paralnt d'indexation , ya t'il une limitte du nombre de champ que l'on peu indexé?
du type de champa indexé etc..?
Marsh Posté le 20-10-2003 à 12:03:39
oui, tous les SGBD ont une limitation pour tous les objets. Mais générallement, ça se comte en milliards pour les dernirères versions, donc pas de souci à ce niveau là.
Bon, pour le nombre de champs dans un même index, ça peut varier entre 64 et 256 généralement, mais jusqu'à 30, sûr et certain, aucun problème.
Marsh Posté le 20-10-2003 à 12:08:54
Spa terrible que je j'ai trouvé là...
The maximum number of keys and the maximum index length is defined per storage engine. See section 7 MySQL Table Types. You can with all storage engines have at least 16 keys and a total index length of at least 256 bytes.
En fin de compte, MySQL semble ne pas aimerles trop gros indexes (m'enfin d'un autre côté, t'es pas censé avoir des indexes trop gros non plus, puisque sinon il ne sont plus performants...)
Marsh Posté le 20-10-2003 à 13:29:36
MagicBuzz a écrit : Spa terrible que je j'ai trouvé là... |
bin enfait moi j'ai indexé 2-3 champs qui sont beacoup utilisés dans les WHERE ;o)
ainsi que chaque clé primaire de chaque tables
je sais pas si c le bon raisonnement a suivre mais bon ;o)
Marsh Posté le 20-10-2003 à 15:20:41
si, c'est ça.
faudra que j'écrire un petit article là-dessus un de ces 4 à mettre dans la faq du forum. mais globalement c'est ça :
clé primaires : index unique
champs souvent utilisés dans les where, index, si possible unique.
toujours utiliser la totalité des champs des indexes. un seul index est utilisé par table et par query (si la table fait l'objet d'un alias dans la requête, alors chaque alias peut utiliser un index différent)
Marsh Posté le 20-10-2003 à 15:26:53
MagicBuzz a écrit : si, c'est ça. |
ouhla ca se complique
1 seul index par table et par query?
on peu avoir 3 index pour une table te se servir d'un seul index dans la requete? non ? ;o)
Marsh Posté le 20-10-2003 à 15:35:21
Bah pour faire simple :
Tu peux avoir autant d'index que tu veux sur une table (plus tu en met, et plus ça va bouffer de la place et des ressources dans ta base).
Mais lors d'une requête, le parseur SQL va choisir quel index correspond le mieu à tes critères pour chaque requête portant dans chaque table.
Un exemple dans quelques instants
Marsh Posté le 20-10-2003 à 15:37:18
je tombe sur ce topic et j'avais remarqué le même comportement, char <=3 ben ça donnait char sinon ça donnait varchar.
et là je suis en MySQL 4.0.14 (faudra que j'upgrade) et je remarque que à l'exception de 2 champs. Je ne m'explique même pas pourquoi car j'ai des char(255) dans mon modèle ET dans la base de données (que MySQL n'a donc pas jugé utile de convertir en varchar(255)
Marsh Posté le 20-10-2003 à 15:41:27
MagicBuzz a écrit : Bah pour faire simple : |
je te remercie
Marsh Posté le 20-10-2003 à 15:41:29
table t1
t1.c1
t1.c2
t1.c3
t1.c4
table t2
t2.c1
t2.c2
t2.c3
t2.c4
t1.c1 et t2.c1, sont les clés primaires de tes tables.
t2.c2 est une clé étrangère pointant sur t1.c1. Il y a un index dessus
t2.c3 contient un flag sur lequel tu fait systématiquement un critère.
Tu vas donc créer les indexes suivant :
IDX1 (t1.c1) UNIQUE
IDX2 (t2.c1) UNIQUE
IDX3 (t2.c2, t2.c3) NON-UNIQUE
Maintenant, la requête :
select t2.c4
from t1, t2
where t1.c1 = '123'
and t2.c2 = t1.c1
and t2.c3 = 'ACTIVE'
Le SGBD va utiliser les index IDX1 pour la première (critère t1.c1 = '123', membre de l'index) et l'index IDX3 pour la seconde (critère t2.c2 = t1.c1 et t2.c3 = 'ACTIVE')
Par contre, imagine que tu rajoutes un critère sur c2.c1, style (and c2.c1 > 1000), vu que c'est un index unique, même si le critère est plus vague, c'est IDX2 qui va être utilisé à la place de IDX3.
Et imagine aussi que IDX3 porte aussi sur t2.c1, à ce moment il sera plus lent que s'il ne porte que sur t2.c2 et t2.c3, puisqu'il sera obligé de faire une "NESTED LOOP" dans l'index, ce qui est catastrophique niveau perfs (mais c'est toujours mieu que pas d'index du tout )
Marsh Posté le 20-10-2003 à 15:41:36
drasche a écrit : je tombe sur ce topic et j'avais remarqué le même comportement, char <=3 ben ça donnait char sinon ça donnait varchar. |
oauis c louche ;o)
Marsh Posté le 20-10-2003 à 15:45:21
drasche a écrit : je tombe sur ce topic et j'avais remarqué le même comportement, char <=3 ben ça donnait char sinon ça donnait varchar. |
des char(255) c'est limite goret là par contre...
géneralement, un char on utilise ça pour écrire un code, qui sera indexé, genre un code produit, une code famille ou autre... Pas pour stocker du texte, parceque là, le gain que tu as avec un champ de taille fixe, tu le perds en surface occupée par le fichier sur le disque et en mémoire...
Marsh Posté le 20-10-2003 à 15:52:40
c'est pas tellement la question, c'est plutôt que je me demande ce qui régit le mécanisme derrière pour choisir char ou varchar
bon en fait je viens de tester un truc, j'avais un varchar(255) suivi d'un mediumtext, et en fait c'est le seul que j'avais. J'arrivais pas à le changer en char, donc je supprime le champ mediumtext à tout hasard et là il me permet le changement de type en varchar. A mon avis c'était la présence d'un champ de type text/blob qui a influencé le choix de MySQL.
Marsh Posté le 20-10-2003 à 16:03:17
Je sais que souvent les champs de ce type foutent le bordel dans les bases de données.
Par exemple lors d'une connection ODBC, un champ de type "text" sous SQL Server (un blob au format texte) va provoquer une erreur s'il n'est pas en dernière position dans la requête.
Avec Oracle, c'est encore mieu, par ODBC, ça plante tout court. Par OLE DB, ça merde à mort aussi, mais y'a une astuce pour que ça marche.
En fait, tant que ces champs peuvent être évités, il faut les éviter comme la peste, d'autant plus qu'ils ne peuvent pas être indexés avec des indexes classiques, donc offrent des performances catastrophiques dès qu'on fait un like dedans par exemple.
Marsh Posté le 20-10-2003 à 16:06:42
pour ça pas de problème, j'en fais un usage parcimonieux et de toute façon, je suis sur PHP donc en natif MySQL directement.
Marsh Posté le 20-10-2003 à 16:37:48
à mon avis ça empêche pas les merdes
si Oracle et M$ ont ce bug connu depuis 10 ans et arrivent pas à s'en dépatouiller, alors même si MySQL a des points forts, je doute qu'ils soient passé à travers ce bordel sans y laisser des plumes
Marsh Posté le 20-10-2003 à 16:42:46
j'ai bien un argument fallacieux mais on va crier au troll (MySQL c'est libre donc forcément c'est corrigé depuis 10 ans ) Voilà j'ai quand même balancé discrètement mon troll
ben si le bug existe aussi chez MySQL je suppose que je le découvrirai dans pas très longtemps
Marsh Posté le 20-10-2003 à 16:53:40
bah déjà, le fait que ton char soit converti ou non quand il y a un text à côté me semble être une manifestation oculte du bug en question
Marsh Posté le 20-10-2003 à 19:20:44
Alors ca !
C'est bien chiant !
Qu'est ce que j'en ai a faire de perdre de l'espace disque si c'est pour gagner en performances ?
Toutes les applis n'ayant pas le même profil, cette limitation de mySQL me semble dingue.
Cai super lourd si tu as des champs char assez longs et répétés, et surtout de taille fixe comme moi !
Débile même ! Perte de performance pour un gain disque NUL !
Marsh Posté le 20-10-2003 à 19:54:56
drasche a écrit : je tombe sur ce topic et j'avais remarqué le même comportement, char <=3 ben ça donnait char sinon ça donnait varchar. |
Normalement, il ne fait ca QUE si les ligne sont de taille variable (il y a au moins un varchar/text). Ce qui est logique : dès qu'il y a une colonne ayant une taille non fixe, alors toute la ligne est de taille variable. Quitte à perdre les avantages des lignes de taille fixe, autant aller jusqu'au bout de la logique et convertir en varchar() toutes les colonnes de texte de longueur > 3
Marsh Posté le 20-10-2003 à 22:47:02
tetedeiench a écrit : Alors ca ! |
Non, tu ne gagnes pas en perfs si tu bouffe plus d'espace.
Réfléchit avec ton cerveau, il est là pour ça.
Si ta table est plus grosse :
1) Les accès sur le disque représenteront forcément un parcours plus grand de têtes, donc un ralentissement majeur (en effet, sur un disque, c'est bien les déplacements des têtes qui sont les plus importants niveau performance)
2) Plus ta table est grosse, plus elle prendra de la place en mémoire, et plus tu auras besoin de charger/décharger des données lors des requêtes, donc plus d'accès disques.
Le gain de perfs avec un char est vrai quand t'as 1000 lignes. Au delà c'est au contraire un facteur bloquant.
C'est pas pour élever des moules dans le sahara que les développeurs de SGBD ont inventé les blob, qui ne sont qu'un int32 faisant référence à une zone du disque jamais utilisée plutôt que de perdre de la place dans les données des tables. C'est bien pour réduire la quantité d'informations à lire/traîter lorsqu'on fait des requêtes.
Sinon, un varchar n'a d'inconvénient que le fait que les champs sont de taille variable, donc ça force le moteur du SGBD à faire des calculs d'offset supplémentaires lors du traîtement des champs.
Seulement, si tu utilises ton champs pour un critère (seul moment où tu auras en effet besoin de lire très rapidement les valeurs) alors tu auras certainement fait un index (sinon je te fou mon poing sur ton gros nez) et par conséquent la différence de perfs est absoluement nulle (les calculs d'offset sont déjà présents dans l'index)
Marsh Posté le 20-10-2003 à 22:48:03
mrBebert a écrit : Normalement, il ne fait ca QUE si les ligne sont de taille variable (il y a au moins un varchar/text). Ce qui est logique : dès qu'il y a une colonne ayant une taille non fixe, alors toute la ligne est de taille variable. Quitte à perdre les avantages des lignes de taille fixe, autant aller jusqu'au bout de la logique et convertir en varchar() toutes les colonnes de texte de longueur > 3 |
Pour info, un champ de type "text" est de taille fixe au niveau de la table. La valeur est stockée à un autre endroit de la base. C'est ni plus ni moins qu'un pointeur, ou une "inode" quand on se met d'un point de vue système de fichier.
Marsh Posté le 21-10-2003 à 07:20:42
MySql indique que la table est à un format dynamique lorsqu'il y a une colonne 'text'. Mais c'est peut être effectivement géré différemment du varchar
Marsh Posté le 21-10-2003 à 09:26:17
Ben disons que si le type "text" était géré directement dans l'espace de stockage de la table, alors MySQL serait incapable d'offrir les performances qu'il offre actuellement, puisqu'un format "text" peut généralement contenir jusqu'à 4 Go de données (voir plus sur certain SGBD). A partir de là, je vois pas comment il serait possible de traîter efficacement tout ce volume de données lors de la recherche d'une ligne, simplement lors du chargement des autres colonnes en mémoire depuis le disque (parcequ'un déplacement de 4 Go sur un disque, ça fait un mouvement des têtes sur le disque, donc énorme temps de latence, surtout si c'est pour chaque ligne). Et le pire serait la place perdue, puisqu'une table avec du varchar par exemple est stockée avec des trous, permettant aux varchar de grossir sans devoir décaler toutes les données à chaque fois. Là avec une telle amplitude, le place perdue serait énorme, et les déplacement très fréquents.
Marsh Posté le 20-10-2003 à 09:48:29
Voila
je sais qu'il faut eviter les champs de taille variable
Mais ce que je comprend pas c'ets que MySql force mes CHAR en VARCHAR
quand je met un champ de type CHAR (10) il me met VARCHAR automatiquement
pourquoi?
un char ne peu pas depasser 10 caractères? !!!
ou alors c'est le systeme d'optimisation des base MySQL d'easyPHP qui merde?
merci d'avance