
On Mon, Sep 01, 2008 at 03:06:53AM +0200, Daniel Caillibaud wrote:
Bonjour,
Je me suis écrit la petite fonction suivante (en bash) pour découper un dump mysql par tables (je rajoute ici des retours chariot pour la lisibilité).
split_sqldump() { if [ $# -lt 1 ] ; then echo "Il faut passer le fichier de sqldump en argument (et éventuellement un préfixe en 2nd arg)"; elif [ ! -f "$1" ] ; then echo "Le fichier '$1' n'existe pas"; else prefix="$2"; file="$1"; awk -F '`' ' BEGIN {l=0;lastl=1; tb=""; prefix="'"$prefix"'"; file="'"$file"'"} {l=l+1} /DROP TABLE IF EXISTS/ { lasttb=tb; tb=$2; if (lasttb != "") { print "echo \"[`date '"'+%T'"'`] " lasttb " (" lastl "," l-1 ")\""; print "sed -ne '"'"'" lastl "," l-1 " p; " l " q;'"'"' < \"'"$file"'\" > " prefix lasttb ".sql"; } lastl=l; } END { print "echo \"[`date '"'+%T'"'`] " tb " (" lastl ",fin)\""; print "sed -ne '"'"'" lastl ",$ p;'"'"' < \"'"$file"'\" > " prefix tb ".sql"; } ' < $file; fi; };
Salut, Je répond un peu à l'arrache parce que je n'ai pas le temps de te faire une réponse complète mais voilà quelques idées : 1) première règle quand tu fais du parsage, tu t'arranges pour ne parser qu'une seule fois (toi tu parses <nombre de tables>+1 fois, c'est ultra dégueulasse, et évidemment les perfs s'en ressentent (sans parler de la scalabilité en O(n) lors que tu pourrais faire du O(1)). Le corollaire est la 2ème règle, qui est encore plus importante : 2) deuxième règle du parsage, tu parses en temps réel dès que c'est possible, i.e. tu fais comme si tu parsais un stream, et tu fournis les réponses asap. Je m'explique : - gcc prend un fichier, le parse, puis fait sa sauce. Il met tout le fichier en ram, puis commence à travailler, puis une fois qu'il a fini il sort ce qu'il veut. Un peu comme tu as fait, sauf que toi tu as fait un for (i=0; i < 100; i++) autour de l'appel :-) - sort parse un stream, mais il ne commence à printer qu'une fois qu'il a tout le stream en ram. évidemment c'est mieux mais toujours pas top. - cat, lui, il parse un stream et en plus il affiche au fûr et à mesure (modulo le cache éventuel sur stdout), c'est le must du parsage. En général, les scripts sed/awk fonctionnent comme ça (par ligne, donc). Donc pour finir, la bonne solution : tu écris un bête script (en sed, awk, perl ou ce que tu veux) qui lit une ligne, réalise un traitement sur cette ligne (en particulier un traitement dépendant de l'état, et un traitement qui peut changer l'état), puis tu réitère jusqu'à la fin. Pas de stockage nulle part, et un seul parsage. Pour ton cas, et en perl, ça donne (écrit dans le mail donc non testé, désolé :-)) : ----- #!/usr/bin/perl use strict; use warnings; my $db = undef; # Current database name my $table = undef; # Current table name my $fh = undef; # Current filehandle while (<>) { if (/^CREATE DATABASE .* `([^`]+)`/) { $db = $1; } elsif (/^DROP TABLE IF EXISTS `([^`]+)`/) { $table = $1 close $fh if $fh; # pas nécessaire vu que le open # suivant ferme automatiquement # le filehandle. open $fh, '>', "$db.$table.sql"; } if ($db and $table) { print $fh $_ if $fh; } } close $fh; ----- Je ne suis pas sûr que ça donne strictement le même résultat que ton script vu sa complexité, mais bon ça me semble être un début pour toi. Désolé encore une fois si j'ai loupé quelque chose dans ton mail, et j'espère t'avoir aidé un peu. N'hésites pas à commenter. ++ Stéphane. PS: Pour une réponse pure bash, c'est tout à fait faisable si tu la veux, mais ce sera infiniment plus lent. -- /// Stephane Jourdois /"\ ASCII RIBBON CAMPAIGN \\\ ((( Consultant securite \ / AGAINST HTML MAIL ))) \\\ 157 Bd Davout X /// \\\ 75020 Paris / \ +33 6 8643 3085 ///