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

Hibernate Java Discussion :

Insertion trop lente


Sujet :

Hibernate Java

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    230
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 230
    Points : 132
    Points
    132
    Par défaut Insertion trop lente
    Bonjour,

    j'utilise Hibernate 3 en annotations dans une classe Java que j'utilise en local (pas en mode web...).

    Ma classe possède une dizaine de champs indexés et je dois simplement insérer de manière itérative environ 1,3 million d'enregistrements. J'ai mis en place un petit benchmark qui m'indique que l'appli traite environ 250 lignes par seconde, ce qui est beaucoup trop lent.

    je n'ai rien optimisé car je n'arrive pas à trouver de doc là dessus.

    ma première question sera donc : Où trouver de la doc sur les optimisations ?
    ma seconde est : quelqu'un peut-il me proposer une solution pour optimiser mes traitements en insertion ? Il s'agit d'une insertion pure et simple.
    (Dans un second temps j'utilise aussi avant d'insérer une recherche d'enregistrement afin de vérifier si un enregistrement possédant la même clé existe et si son statut est différent. Mais ce traitement n'est pas celui qui me préoccupe.)

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    230
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 230
    Points : 132
    Points
    132
    Par défaut
    Au temps pour moi j'ai trouvé un chapitre sur le site hibernate.org concernant l'amélioration des perfs, mais je voudrais surtout des avis pro, des retours d'expérience.

    Merci

  3. #3
    Membre confirmé Avatar de djsnipe
    Inscrit en
    Mai 2008
    Messages
    440
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 440
    Points : 493
    Points
    493
    Par défaut
    Pour de l'insertion de masse : le mode batch, surtout si les requêtes sont identiques, mais seuls les paramètres changent, grâce à la mise en cache des PreparedStatement, soit côté Java, soit côté SGBD.

    Comme tu as dû déjà les trouver les infos sont là : http://www.hibernate.org/hib_docs/v3...tml/batch.html

    Sinon, pour des volumes comme ça, attention aux transactions, n'en fait pas qu'une seule (==> peut faire péter le journal de Transactions), ni une par ligne (temps de traitement beaucoupppppppp plus long), mais par paquets d'une taille à déterminer.

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    230
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 230
    Points : 132
    Points
    132
    Par défaut
    Merci pour ta réponse.
    Quand tu dis de faire des transactions par paquets, est-ce que tu parles de flusher et clearer le entitymanager ? Si oui j'ai déjà activé cette fonction avec un nombre de 100 lignes. Comment déterminer ce paramètre ?

    Cordialement

  5. #5
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    for ( int i=0; i<100000; i++ ) {
    Customer customer = new Customer(.....);
    session.save(customer);
    if ( i % 20 == 0 ) { //20, même taille que la taille du paquet JDBC
    //flush un paquet d'insertions et libère la mémoire :
    session.flush();
    session.clear();
    }
    }
    tx.commit();
    session.close();
    + hibernate.jdbc.batch_size 20

    + hibernate.cache.use_second_level_cache false (éventuellement)

    A+

  6. #6
    Membre confirmé Avatar de djsnipe
    Inscrit en
    Mai 2008
    Messages
    440
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 440
    Points : 493
    Points
    493
    Par défaut
    Pas tout à fait, l'action de "flush" correspond au moment où l'entitymanager va effectivement envoyer les ordres à la base de données, le "clear" à libérer la mémoire. Si je prend l'exemple dispo sur la doc Hibernate :

    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
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
     
    for ( int i=0; i<100000; i++ ) {
        Customer customer = new Customer(.....);
        session.save(customer);
        if ( i % 20 == 0 ) { //20, même taille que la taille du paquet JDBC
            //flush un paquet d'insertions et libère la mémoire :
            session.flush();
            session.clear();
        }
    }
     
    tx.commit();
    session.close();
    Il y a une seule grosse transaction. Je te recommande quelque chose du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    if ( i % 20 == 0 ) {
       session.flush();
       session.clear();
    }
     
    if ( i % 1000 == 0 ) {
       tx.commit();
       tx = session.beginTransaction();
    }
    Attention, ce traitement n'est plus une opération atomique. Une exception en cours de traitement ne rollback pas les transactions précédent validées ! Vérifie bien que cette grosse limitation est bien valide par rapport à ton besoin.

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    230
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 230
    Points : 132
    Points
    132
    Par défaut
    Merci pour ces infos. effectivement je préfère conserver l'entité de ma transaction sur l'ensemble de l'insertion. Cela aura-t-il une grande incidence sur les perfs ?

    Sinon j'utilise bien le flush et le clear, j'ai ajouté l'option
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <property name="hibernate.jdbc.batch_size" value="40" />
    j'ai toujours des performances aux environs de 300 enregistrements par seconde. Peut-être j'ai atteint le max au niveau vitesse ? Ca me parait faiblard quand même...

  8. #8
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    Par défaut
    Optimiser hibernate, c'est bien, mais il faudrait également voir du côté de la base de données

  9. #9
    Membre confirmé Avatar de djsnipe
    Inscrit en
    Mai 2008
    Messages
    440
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 440
    Points : 493
    Points
    493
    Par défaut
    Citation Envoyé par esteban Voir le message
    Cela aura-t-il une grande incidence sur les perfs ?
    Fait un petit bench, mais à mon avis, sur 1 million de lignes, ça devrait être quand même significatif ;-). N'oublies pas que ton SGBD est obligé de travailler en mémoire tant que le commit n'est pas fait, ou pire, de swapper si la mémoire ne suffit pas.

    Citation Envoyé par esteban Voir le message
    j'ai toujours des performances aux environs de 300 enregistrements par seconde. Peut-être j'ai atteint le max au niveau vitesse ? Ca me parait faiblard quand même...
    Difficile à dire, le temps dépend de manière macro de 3 facteurs : temps de l'injecteur (ton prog java) + temps réseau (surtout si tu as un mauvais ping) + temps de l'insertion (qui augmente avec les triggers, le nombre d'indexes sur la table, la config du moteur de SGBD, les perfs du disque dur)

  10. #10
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    230
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 230
    Points : 132
    Points
    132
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    Optimiser hibernate, c'est bien, mais il faudrait également voir du côté de la base de données
    Oui faut reconnaitre que Oracle n'est pas forcément le plus fortiche dans ce genre d'utilisations...

  11. #11
    Membre confirmé Avatar de djsnipe
    Inscrit en
    Mai 2008
    Messages
    440
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 440
    Points : 493
    Points
    493
    Par défaut
    Citation Envoyé par esteban Voir le message
    Oui faut reconnaitre que Oracle n'est pas forcément le plus fortiche dans ce genre d'utilisations...
    ça troll dur

  12. #12
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    Par défaut
    Quelque soit la base, si on peu éviter de faire de l'insertion de masse avec des transactions, c'est pas plus mal... ça libère de la mémoire...
    Rien n'empêche de faire un commit() en même temps que le flush() ou d'utiliser l'auto-commit et pas de transaction... mais là, ça dépend de tes besoins

  13. #13
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    230
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 230
    Points : 132
    Points
    132
    Par défaut
    hé hé, mon besoin principal c'est que ça aille vite... Or le commit c'est ce qui va me couter le plus.

Discussions similaires

  1. insertion dans une BD trop lente
    Par jouidos dans le forum Windows Forms
    Réponses: 13
    Dernier message: 01/02/2007, 12h32
  2. [oracle 8.0.5] insert très (trop) lent
    Par icoons dans le forum Oracle
    Réponses: 71
    Dernier message: 13/10/2006, 16h16
  3. boucle while trop lente
    Par atouze dans le forum Access
    Réponses: 17
    Dernier message: 15/06/2005, 16h35
  4. [SAGE] ODBC trop lent
    Par tileffeleauzed dans le forum Décisions SGBD
    Réponses: 1
    Dernier message: 14/11/2004, 09h56
  5. Envoi de mail trop lent
    Par MASSAKA dans le forum ASP
    Réponses: 3
    Dernier message: 15/10/2004, 10h57

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