IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PL/SQL Oracle Discussion :

Commit après 1000 enregistrements


Sujet :

PL/SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Ingénieur
    Inscrit en
    Juillet 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : Congo-Brazzaville

    Informations professionnelles :
    Activité : Ingénieur

    Informations forums :
    Inscription : Juillet 2007
    Messages : 65
    Par défaut Commit après 1000 enregistrements
    Bonjour ,

    je fais des insertions des données qui proviennent d'une autre table via dblink.
    mails la table cible contient plusieurs milliers de lignes , et j'ai des problèmes de performances , je souhaiterais faire des commit après un certain nombre d’enregistrements insérés ,ci-dessous ma requête .


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     insert into ma_table
        (
    	champs_1,
    	champs_2,
    	champs_3,
    	champs_4,
    	champs_5,
    	champs_6,
    	champs_7,
    	champs_7
        )
        select * from la_table_cible@mon_dblink ;
     commit ;

    Toute aide sera la bienvenue , merci .

  2. #2
    Membre Expert

    Homme Profil pro
    Inscrit en
    Mars 2010
    Messages
    536
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 536
    Par défaut
    Bonjour,

    Avant de pouvoir vous donner un conseil, j’aurai aimé connaitre comment êtes vous arrivé à savoir que "commiter" tous 1000 lignes améliorera la performance de votre select?

    Cary Millsap: a dit une chose très sensée: ''Why Guess when you can know?'' Pourquoi devinez lorsque vous pouvez savoir ?

    Aussi, dans ce genre de situations, il vaut mieux diagnostiquer correctement le problème de performance avant de lui apporter par la suite le remède qui lui sied parfaitement.

    Ceci dit j’ai quelques conseils à vous donner quand même:
    Si votre table d’insertion n’a ni trigger ni contrainte d’intégrité (FK) pensez alors à utiliser un ''direct path load'' en utilisant le hint /*+ append */.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    INSERT /*+ append */ INTO ma_table
        (
    	champs_1,
    	champs_2,
    	champs_3,
    	champs_4,
    	champs_5,
    	champs_6,
    	champs_7,
    	champs_7
        )
    select champs_1,
    	champs_2,
    	champs_3,
    	champs_4,
    	champs_5,
    	champs_6,
    	champs_7,
    	champs_7 
      from la_table_cible@mon_dblink ;
    Cela ne génèrera pas d’UNDO sur la table et les indexes seront chargés avec un ''bulk collect''. Si certaines conditions supplémentaires sont vérifiées il n’y aura pas de Redo aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Table Mode    Insert Mode     ArchiveLog mode      result
    -----------   -------------   -----------------    ----------
    LOGGING       APPEND          ARCHIVE LOG          redo generated
    NOLOGGING     APPEND          ARCHIVE LOG          no redo
    LOGGING       no append       ""                   redo generated
    NOLOGGING     no append       ""                   redo generated
    LOGGING       APPEND          noarchive log mode   no redo
    NOLOGGING     APPEND          noarchive log mode   no redo
    LOGGING       no append       noarchive log mode   redo generated
    NOLOGGING     no append       noarchive log mode   redo generated
    http://asktom.oracle.com/pls/asktom/...:5280714813869

    Attention ceci représente une solution valable lorsque vous ne faites pas de ''delete'' fréquents sur la table où lorsque vous insérez dans une table vide. En effet le ''direct path load'' insert directement au dessus du High Water Mark et n’utilise aucun espace libre existant dans les blocks de données.

    Si vous partez d’une table vide, ou si le volume de données à insérer est largement supérieur au volume de données actuel de la table, il vaut mieux alors mettre tous les indexes dans un statut ‘DISABLED’ et faire un ‘rebuild’ après la fin de l’insert.

    Si vous lisez le nouveau libre de Jonathan Lewis, vous réfléchiriez à plusieurs reprises avant d’utiliser un select *. Je vous conseille alors de remplacer le select * par les colonnes nécessaires à l’insert uniquement.

    Est-ce que votre table est partitionnée ? d'autres suggestions peuvent être envisagées dans ce cas aussi

    Enfin, comme je l’ai signalé au début, pensez à tracer votre insert/select via l’event 10046 afin de connaître réellement où se trouve l’origine du ralentissement de votre insert

  3. #3
    Membre confirmé
    Profil pro
    Ingénieur
    Inscrit en
    Juillet 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : Congo-Brazzaville

    Informations professionnelles :
    Activité : Ingénieur

    Informations forums :
    Inscription : Juillet 2007
    Messages : 65
    Par défaut
    Bonjour Mohamed ,


    Bravo, c'est ce qu'on appelle par une réponse remplie de bon sens .

    Effectivement je pensais que les insertions étaient stockées dans les UNDO, c'est pourquoi j'ai pensé qu'en effectuant des commit intermédiaires , j'aurais résolu mon problème mais apparemment non .. .

    Ceci dit mon contexte est celui ci:
    Ma table contient déjà des données (des millions de lignes) précédemment enregistrées, elle a aussi des contraintes de Primary key , de Unique Key mais pas de FK .

    Si je fais un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM la_table_cible@mon_dblink ;
    pour récupérer mes données c'est parce que de l'autre côté ma table cible n'est qu'une vue qui contient les noms de colonnes des tables dont je désire récupérer les données .

    Parraport à vos conseils , je pense que la solution :
    Si vous partez d’une table vide, ou si le volume de données à insérer est largement supérieur au volume de données actuel de la table, il vaut mieux alors mettre tous les indexes dans un statut ‘DISABLED’ et faire un ‘rebuild’ après la fin de l’insert.
    serait adaptée à mon contexte .

    La table cibles sont partitionnée , ma table de destination (celle qui doit contenir les données extraites ) est aussi partitionnée .

    Merci toujours pour vos conseils si éclairés .

  4. #4
    Membre Expert

    Homme Profil pro
    Inscrit en
    Mars 2010
    Messages
    536
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 536
    Par défaut
    Citation Envoyé par cornnery Voir le message
    La table cibles sont partitionnée , ma table de destination (celle qui doit contenir les données extraites ) est aussi partitionnée .
    Si les deux tables sont partitionnées des deux côtés, vous pouvez faire un insert/select par partition. Et dans ce cas il faudra uniquement "disabler" les indexes locaux correpondants à la partition p1 comme suit par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    mhouri > alter index part_ind modify partition p1 unusable;
     
    Index altered.
     
    mhorui> select index_name, status
      2  from user_ind_partitions
      3  where status = 'UNUSABLE';
     
    INDEX_NAME                     STATUS                                                                                   
    ------------------------------ --------                                                                                 
    PART_IND                       UNUSABLE                                                                                 
     
    INSERT /*+ append */ INTO ma_table partition (p1)
        (
    	champs_1,
    	champs_2,
    	champs_3,
    	champs_4,
    	champs_5,
    	champs_6,
    	champs_7,
    	champs_7
        )
    SELECT champs_1,
    	champs_2,
    	champs_3,
    	champs_4,
    	champs_5,
    	champs_6,
    	champs_7,
    	champs_7 
     FROM la_table_cible@mon_dblink 
     WHERE cle_partition = :cle_qui_correspond a la partition p1
    ;
     
    mhouri> alter index part_ind rebuild partition p1;
     
    Index altered.
     
    mhouri> select index_name, status
      2  from user_ind_partitions
      3  where status = 'UNUSABLE';
     
    no rows selected
    Et ainsi de suite pour les autres partitions.

  5. #5
    Membre confirmé
    Profil pro
    Ingénieur
    Inscrit en
    Juillet 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : Congo-Brazzaville

    Informations professionnelles :
    Activité : Ingénieur

    Informations forums :
    Inscription : Juillet 2007
    Messages : 65
    Par défaut
    Hi Mohamed ,

    intéressant , sauf que dans mon cas la table n'a pas été construite avec des index locaux , mais avec un index global, dans ce cas dois je le "disabler" de façon globale et le reconstruire ? ça ne serait pas un traitement lourd pour une table contenant des millions de ligne ???

    Merci

  6. #6
    Membre Expert

    Homme Profil pro
    Inscrit en
    Mars 2010
    Messages
    536
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 536
    Par défaut
    Citation Envoyé par cornnery Voir le message
    Hi Mohamed ,

    intéressant , sauf que dans mon cas la table n'a pas été construite avec des index locaux , mais avec un index global, dans ce cas dois je le "disabler" de façon globale et le reconstruire ? ça ne serait pas un traitement lourd pour une table contenant des millions de ligne ???

    Merci
    Ce que je vous ai suggéré a un sens pour les indexes locallement partitionnés car on ne ''disable'' que la partition vide (ou à insérer) et on refait le 'rebuild' après une fois cette partition chargée.

    Pour les indexes globaux, cela n'a pas de sens surtout lorsque le volume de données apporté par l'insert est largement inférieur au volume des données avant l'insert. En d'autres mots, si vous insérez 1 million de lignes dans une table qui en contient déjà 10 millions, vous devriez dans ce cas éviter de faire le ''disable'' des indexes avant insert; autrement vous auriez à faire un rebuild d'un index de 11 millions de lignes; ce qui n'est pas négligeable

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 25/02/2008, 21h26
  2. mise en page de la saisie aprés l'enregistrement dans une bd
    Par biba158 dans le forum Interfaces Graphiques en Java
    Réponses: 13
    Dernier message: 20/06/2007, 15h29
  3. Réponses: 4
    Dernier message: 20/06/2007, 11h24
  4. Réponses: 4
    Dernier message: 08/01/2007, 13h06
  5. Réponses: 2
    Dernier message: 28/11/2005, 10h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo