Modification d'une grosse table Comment ajouter un champs dans une grosse table
#1
Posté 29 septembre 2011 - 07:51
Nous avons une table relativement grosse dans notre base de donnée mysql (600 000 enregistrements, 4.5 Go).
A chaque modification de la structure de cette table (par exemple l'ajout d'un simple champ varchar), le serveur mouline et rend le site inaccessible pendant plusieurs dizaines de minutes.
Y-a-t-il une méthode saine pour ajouter un champ à ce type de table, sans faire planter le serveur ?
Merci d'avance pour votre aide !
#2
Posté 29 septembre 2011 - 09:51
Sans plus d'infos, je pense que ça vient d'un problème de conception de votre base de données.
#3
Posté 29 septembre 2011 - 10:48
Je ne sais pas comment ça se passe avec mysql, mais avec postgresql un ajout de colonne est rapide tant qu'on ne met pas de valeur par défaut à la nouvelle colonne. Comme l'ajout de la colonne lui-même est bloquant, la solution consiste alors à ajouter la colonne sans défaut, puis mettre le défaut sur la colonne, puis initialiser cette nouvelle colonne avec cette valeur par défaut. Evidemment, cette dernière opération peut être un peu longuette suivant la taille de la table, et avec mysql le type de base (MyISAM ou Innodb) va donc influencer le type de lock et donc le fait que ça bloque ou pas.
Autre solution, créer une autre table qui sera utilisée avec une jointure avec la première, éventuellement avec une vue pour simplifier les choses en lecture.
Jacques.
#4
Posté 29 septembre 2011 - 11:03
Merci pour vos réponses
Nous devons ajouter un champs suite à l'évolution de notre site, nécessité de stocker de nouvelles infos.
Lors de l'ajout de ce champs, aucune valeur par défaut n'est créée :
ALTER TABLE `matable` ADD `monchamp` VARCHAR(10) NOT NULL ;
La solution pourrait effectivement être de créer une autre table jointe, mais j'aurais préféré ajouter ce champs dans la table existante.
Ce message a été modifié par fred078 - 29 septembre 2011 - 11:03.
#6
Posté 29 septembre 2011 - 11:29
#7
Posté 29 septembre 2011 - 11:30
En fait je la met a NOT NULL pour pouvoir faire mes tests sur champs vide (... WHERE monchamp='').
Par "pas de valeur par défaut" j'entendais, pas de :
ALTER TABLE `matable` ADD `monchamps` VARCHAR(10) NOT NULL DEFAULT 'valeur';
_AT_captain_torche :
Ca arrive moins de 1 fois par an, et c'est probablement une des dernieres fois que ca arrive.
Ce message a été modifié par fred078 - 29 septembre 2011 - 11:32.
#8
Posté 29 septembre 2011 - 12:01
Note aussi que le comportement peut éventuellement différer entre une table myIsam et une table InnoDB.
Autre alternative si la jointure ne te convient pas: créer une nouvelle table en copiant l'ancienne (un truc genre create table nouvelle as select *,cast(nouvelle_valeur_par_défaut as type) as nouvelle colonne from ancienne), puis remplacer l'ancienne table par la nouvelle (2 x alter table rename). Le tout avec une transaction bien placée suivant tes circonstances (si tu peux empêcher les écritures dans la table pendant l'opération, une courte transaction autour des deux alter table rename suffira).
Jacques.
#9
Posté 29 septembre 2011 - 13:26
Donc si je comprends bien, mes tables seront moins lourdes si a partir du moment où un champs est vide, je le met en NULL plutôt que de le laisser vide ?
Je vais essayer d'ajouter ce champs en spécifiant le NULL plutôt qu'un champs vide car si je peux éviter les jointures ça m'arrange (trop de mauvais souvenirs de mauvaises performances avec les jointures...).
Ce message a été modifié par fred078 - 29 septembre 2011 - 15:42.
#10
Posté 29 septembre 2011 - 15:45
clients commençant par A dans la table "matable_a", clients qui commencent par B dans la table "matable_b", etc... * 26 tables.
Je penses que je vais en faire hurler quelques un mais c'est ce qui me parait le plus simple et le moins générateur de problèmes sur le long terme (multiplication du volume de données : +30% chaque année)...
#11
Posté 29 septembre 2011 - 15:51
Quels sont les champs que vous ajoutez ? Des informations non prévues ?
Si c'est le cas, il faudrait envisager une seconde table 'informations', ainsi qu'une jointure.
#12
Posté 29 septembre 2011 - 15:55
Voilà encore une idée géniale qui a de l'avenir.
#13
Posté 29 septembre 2011 - 16:14
Oui, ce sont des infos supplémentaires nécessaire suite à l'évolution de certaines fonctionnalités.
En fait cette table est composée de 2 "gros" champs contenant 99% du volume, et une 15ène d'autres "petits" champs.
J'ai testé les jointures il y a quelques temps mais j'ai été confronté à de nombreux problèmes de performances. Donc, même si notre infra à beaucoup évolué depuis (et que les structures de nos tables ont été optimisées via des INDEX plus judicieux), j'hésite à me relancer la dedans...
_AT_Arlette :
Non, il ne s'agit pas de Merci Facteur, c'est pour un autre site. Mais merci pour ton compliment
Ce message a été modifié par fred078 - 29 septembre 2011 - 16:15.
#14
Posté 29 septembre 2011 - 16:15
Je pense qu'une bonne jointure bien faite (i.e. avec les bons index) ça devrait être nettement plus simple.
Jacques.
#15
Posté 29 septembre 2011 - 16:16
Quant à merci facteur (Qui est effectivement un excellent concept), les modérateurs et administrateurs ont accès à ton mail d'inscription
#16
Posté 29 septembre 2011 - 16:26
Mais bon, si vous me déconseillez aussi nettement cette méthode je vais vous suivre et faire quelques tests de jointures pour voir ce que ça donne.
#17
Posté 30 septembre 2011 - 23:14
fred078, le 29 septembre 2011 - 07:51, dit :
Nous avons une table relativement grosse dans notre base de donnée mysql (600 000 enregistrements, 4.5 Go).
A chaque modification de la structure de cette table (par exemple l'ajout d'un simple champ varchar), le serveur mouline et rend le site inaccessible pendant plusieurs dizaines de minutes.
Y-a-t-il une méthode saine pour ajouter un champ à ce type de table, sans faire planter le serveur ?
Merci d'avance pour votre aide !
C'est sous phpmyadmin que ça plante ? En ssh, ça donne quoi ?
vous pourrez le monétiser efficacement avec Adverteasy.fr
Vous pourrez de plus devenir micro sponsor avec un simple code allopass
#20
Posté 14 octobre 2011 - 08:59
fred078, le 14 octobre 2011 - 05:09, dit :
Simplement pour vous tenir au courant, nous avons finalement choisi de scinder notre table en plusieurs table.
Cela a résolu nos problèmes.
Merci pour vos conseils.
Quand on a une table très grosse et qui en plus grossit au fil du temps, le plus simple est en effet souvent de la scinder en créant 1 nouvelle table par semaine ou par mois ou sur une autre périodicité adaptée aux données qu'on traite.
C'est bien que tu aies pu résoudre ton problème.
vous pourrez le monétiser efficacement avec Adverteasy.fr
Vous pourrez de plus devenir micro sponsor avec un simple code allopass



Haut













