Accélérons le transport !

Le temps, c’est souvent ce qu’il nous manque lors d’opérations. Que ce soit en production ou sur des environnements de qualification, nos amis chefs de projet sont souvent amenés à raccourcir les délais.
De ce fait, des opérations qui pouvaient prendre des jours sont amenées à être compressés pour tenir sur des demi-journées.
Parmi ces opérations, on peut compter les migrations par import/export.
Récemment, il m’a été demandé de réaliser un transport de base, opération relativement simple qui a pris 18h. La base de données étant hautement indexée, les 3/4 de l’import a été consommé par la recréation des index.
Par « chance », les données sources n’étant pas correctes, j’ai dû réaliser un nouveau transport des mêmes données mais en ayant cette fois une fenêtre de 6h d’intervention.
Dilemme ? Passer de 18h à 6h…
Heureusement, après discussion avec un collègue, une méthode très simple et rapide nous est apparue ! DATA PUMP !! Nouvel outil, révolutionnaire !
Blague à part, Data Pump, l’outil d’import/export apparu en 10g est un excellent moyen d’accélérer les traitements. Comment ? Tout simplement parce qu’il est malléable.
L’idée est d’effectuer notre import uniquement au niveau des données. Les index et contraintes seront gérés indépendamment par la suite.
Comment faire ?
Dans un premier temps, nous allons effectuer un export dans ce qu’il y a de plus banal.

$ expdp \'/ as sysdba\' directory=EXP_PGR dumpfile=EXPDP_PP.dmp logfile=EXPDP_PP.log schemas=toto,tata,titi

Voilà, nous avons notre export !
Maintenant, nous devons faire en sorte de générer 2 fichiers, à savoir un script SQL de création des index et un script pour les contraintes d’intégrité.

$ impdp \'/ as sysdba\' directory=TMP_IMP dumpfile=EXPDP_PP.dmp include=INDEX sqlfile=index.sql
$ impdp \'/ as sysdba\' directory=TMP_IMP dumpfile=EXPDP_PP.dmp include=CONSTRAINT sqlfile=constraints.sql

Et voilà, par l’utilisation des clauses INCLUDE et SQLFILE, nous avons nos deux fichiers SQL.
En soit, l’opération ne sera pas accéléréé mais nous avons maintenant la possibilité de modifier le script pour y ajouter du parallélisme (à condition bien sûr d’être en Enterprise Edition 😉 ).
Voici un petit script bash qui va nous permettre de manipuler et d’épurer notre fichier :

#!/bin/bash
## Récupération des clauses de stats non-nécessaires tout en générant une sauvegarde
REMOVE_AFTER=`grep -n "SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS" index.sql | cut -d: -f1`
FILE_LENGTH=`cat index.sql | wc -l`
sed -i\".bak\" '${REMOVE_AFTER},${FILE_LENGTH}d' index.sql
## ACTIVATION DU PARALLELISME POUR LE CALCUL DES INDEX
## adaptez le degré de parallélisme en fonction de votre environnement.
sed -i.bak2 -e "s/PARALLEL 1 ;/PARALLEL 6;/g" index.sql
exit 0

Et voilà ! Nous avons en sortie un script SQL contenant les DDL des index avec ici un Degré de Parallélisme (DOP) de 6 :
Il ne nous reste plus qu’à importer nos données et à lancer nos deux scripts :

$ impdp \'/ as sysdba\' directory=TMP_IMP dumpfile=EXPDP_PP.dmp logfile=IMPDP_R.log exclude=INDEX,CONSTRAINT schemas=toto,tata,titi
$ sqlplus / as sysdba
SQL> @index.sql
SQL> @constraints.sql
SQL> exec dbms_stats.gather_database_stats(degree=>6); -- calcul des stats de la BDD parce que nous les avons exclus de l'import et du script et que nous voulons une base propre

En espérant vous avoir accéléré dans vos déplacements 🙂