Performances de sed

Daniel Caillibaud ml.dcailli at free.fr
Mon Sep 1 03:06:53 CEST 2008


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;
};

Ça marche bien mais c'est assez lent. Même si c'est pas très grave ici (sur un desktop, et pas lancé très souvent) je me
dis qu'il doit y avoir une façon de faire plus intelligente qui m'a échappée.

Avec un fichier test.sql de 16Mo et 100 tables, j'ai

$ time split_sqldump_ok test.sql prefix_ > todo
real	0m2.182s
(donc c'est pas awk qui patauge tant que ça)

Ça donne du
$head todo
echo "[`date '+%T'`] access (22,50)"
sed -ne '22,50 p; 51 q;' < "test.sql" > prefix_access.sql
echo "[`date '+%T'`] accesslog (51,704)"
sed -ne '51,704 p; 705 q;' < "test.sql" > prefix_accesslog.sql
echo "[`date '+%T'`] actions (705,742)"
sed -ne '705,742 p; 743 q;' < "test.sql" > prefix_actions.sql
echo "[`date '+%T'`] actions_aid (743,766)"
sed -ne '743,766 p; 767 q;' < "test.sql" > prefix_actions_aid.sql
echo "[`date '+%T'`] adodb_logsql (767,798)"
sed -ne '767,798 p; 799 q;' < "test.sql" > prefix_adodb_logsql.sql

Jusque là tout va bien, mais à l'éxécution ça donne
[02:53:20] access (22,50)
[02:53:20] accesslog (51,704)
[02:53:20] actions (705,742)
[02:53:20] actions_aid (743,766)
[02:53:20] adodb_logsql (767,798)
...
[02:53:49] flood (2868,2896)
[02:53:50] forum (2897,2924)
[02:53:51] history (2925,2973)
[02:53:52] languages (2974,3009)
...
[02:55:00] vocabulary_node_types (32599,32640)
[02:55:02] votingapi_cache (32641,32704)
[02:55:04] votingapi_vote (32705,32764)
[02:55:06] watchdog (32765,41897)

Soit presque 3min pour parser partiellement (de moins en moins certes) test.sql 100 fois.

J'ai essayé d'ajouter du 
sed -i '1,X d' test.sql
après chaque "sed -e" mais c'est pire (pas très étonnant, ça réduit le fichier au fur et à mesure mais l'écriture est coûteuse).

Avec l'ajout de
 if (l>5000) { print "sed -i '"'"'1," l-1 " d;'"'"'  \"'"$file"'\"";l=1}
ça efface le début du fichier dès que le point de départ dépasse la 5000e ligne, et on tombe à 45s. Avec 1000 à la place de
5000, j'arrive à 30s mais je trouve ça élevé. Y'a qqchose d'évident qui m'a échappé (vu l'heure c'est possible) ?

Merci pour les suggestions.

-- 
Daniel

Vous ne croyez tout de même pas sérieusement que l'on ne peut inclure
dans une théorie physique que des grandeurs observables.
Albert Enstein.


More information about the Shell mailing list