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 :

Problème de performance


Sujet :

Hibernate Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de Julien Bodin
    Homme Profil pro
    Devops
    Inscrit en
    Février 2009
    Messages
    474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Devops
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 474
    Par défaut Problème de performance
    Bonjour à tous !

    J'ai un gros souci de performance avec Hibernate.
    Pour vous situer un peu le contexte, je dois permettre à un utilisateur de sélectionner un certain nombre de code postaux dans une JTable.

    Dans un premier temps je n'avais qu'une seule colonne "code postal" avec juste le numéro du code postal et ça allait très bien niveau performances.
    Mais à la réflexion je trouve ce système assez peu pratique pour l'utilisateur puisqu'il ne manipule que des code postaux et qu'il n'a pas le nom des communes avec.
    J'ai donc créé une nouvelle table "villes" dans ma base avec toutes les villes des départements gérés par l'application, avec une clé étrangère vers le code postal.
    Et c'est là que les performances chutent. La fenêtre met 5s-6s pour s'afficher, ce qui pourrait presque le faire en fait, le souci étant que le scrolling est extrêmement lent et franchement énervant à utiliser, ce qui est compréhensible d'ailleurs puisque la jtable ne récupère que les données qu'elle doit afficher en fonction de la position de la barre de scroll (si besoin) ce qui démarre le lazy-loading.
    Si je désactive le lazy-loading j'ai un scroll bien fluide mais là j'explose les temps de chargement.
    Si je passe en fetch="join" j'explose les temps de chargement et en plus j'ai 10 fois les mêmes enregistrement dans ma JTable (produit cartésien je suppose).

    Heureusement que je n'ai que 200 code postaux et 2000 communes...

    Comment pourrai-je faire pour optimiser tout cela ?

    Je vous met le mapping d'origine de mes deux classes (CodePostal et Ville) et un petit screenshot pour illustrer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <class name="CodePostal">
    	  <id name="code">
    	  	<generator class="assigned"></generator>
    	  </id>
     
    	  <set name="villes" inverse="true">
    	  	<key column="cp"></key>
    	  	<one-to-many class="Ville"/>
    	  </set>
      </class>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <class name="Ville">
      <id name="id">
      	<generator class="native"></generator>
      </id>
     
      <property name="nom" type="string" column="ville"></property>
     
      <many-to-one name="cp" column="cp"></many-to-one>
      </class>
    Je vous remercie d'avance pour votre aide !
    Images attachées Images attachées  

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    on peut voir le code de ta table?

  3. #3
    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
    Billets dans le blog
    1
    Par défaut
    Quelle version d'hibernate utilises-tu ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Membre éclairé Avatar de Julien Bodin
    Homme Profil pro
    Devops
    Inscrit en
    Février 2009
    Messages
    474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Devops
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 474
    Par défaut
    de ma JTable ?

    C'est une JXTable, que j'utilise cojointement avec les GlazedLists (permet de faire du filtrage/tri). Je vous met tout le code de la fenêtre, y'a pas grand chose de toutes façons :

    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    public class CodePostalDialog extends javax.swing.JDialog {
    	private JLabel jLabel1;
    	private JTextField txtFiltre;
    	private JButton btCancel;
    	private JXTable tCodePostaux;
    	private JScrollPane jscp;
    	private JButton btOK;
    	private static List<CodePostal> selectedCP;
    	private Session currentSession;
     
     
     
    	public CodePostalDialog(JFrame frame, boolean modal) {
    		super(frame, modal);
    		currentSession = HibernateUtil.getSessionFactory().openSession();
    		initGUI();
    	}
     
    	private void initGUI() {
    		try {			
    			//START >>  this
    			FormLayout thisLayout = new FormLayout(
    					"5dlu, 27dlu, 30dlu, 336dlu, 50dlu, 5dlu, 53dlu", 
    					"5dlu, 13dlu, 5dlu, 11dlu, 280dlu, 5dlu, max(p;5dlu)");
    			getContentPane().setLayout(thisLayout);
    			this.setPreferredSize(new java.awt.Dimension(780, 540));
    			this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    			this.setResizable(false);
    			this.addWindowListener(new WindowAdapter() {
    				public void windowClosed(WindowEvent evt) {
    					currentSession.close();
    				}
    			});
    			setSize(getPreferredSize());
    			//START >>  jLabel1
    			jLabel1 = new JLabel();
    			getContentPane().add(jLabel1, new CellConstraints("2, 2, 1, 1, default, default"));
    			jLabel1.setText("Filtre :");
    			//END <<  jLabel1
    			//START >>  txtFiltre
    			txtFiltre = new JTextField();
    			getContentPane().add(txtFiltre, new CellConstraints("3, 2, 5, 1, default, default"));
    			//END <<  txtFiltre
     
    			//START >>  btCancel
    			btCancel = new JButton();
    			getContentPane().add(btCancel, new CellConstraints("7, 7, 1, 1, default, default"));
    			btCancel.setText("Annuler");
    			btCancel.addActionListener(new ActionListener() {
     
    				@Override
    				public void actionPerformed(ActionEvent e) {
    					selectedCP = null;
    					dispose();					
    				}
    			});
    			//END <<  btCancel
    			//START >>  jscp
    			jscp = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    			getContentPane().add(jscp, new CellConstraints("2, 4, 6, 2, fill, fill"));
    			jscp.setAutoscrolls(true);
    			//START >>  tCodePostaux
    			tCodePostaux = new JXTable();
    			tCodePostaux.getSelectionMapper().setEnabled(false);
    			jscp.setViewportView(tCodePostaux);
    			jscp.setAutoscrolls(true);
     
    			//Récupère la liste des code postaux non attribués
    			List<CodePostal> lst = getData();
     
    			//Créé une EventList à partir de la List
    			EventList<CodePostal> lstCP = GlazedLists.eventList(lst);
     
    			//Mise en place du filtrage sur le code postal 
    			MatcherEditor<CodePostal> m = new TextComponentMatcherEditor<CodePostal>(txtFiltre, new CodePostalFilterator());
    			((TextComponentMatcherEditor<CodePostal>) m).setMode(TextMatcherEditor.STARTS_WITH);
    			FilterList<CodePostal> fl = new FilterList<CodePostal>(lstCP, m);
     
    			//Correspondance entre le nom des colonnes et les propriétés de la classe CodePostal
    			String[] propertyNames = {"code", "villes"};
    			String[] columnLabels = {"Code postal", "Villes"};
    			TableFormat<CodePostal> tf = GlazedLists.tableFormat(CodePostal.class, propertyNames, columnLabels);
     
    			//Modèle de la JXTable
    			EventTableModel<CodePostal> etm = new EventTableModel<CodePostal>(fl, tf);
    			tCodePostaux.setModel(etm);
    			final EventSelectionModel<CodePostal> es = new EventSelectionModel<CodePostal>(fl);
    			es.addListSelectionListener(new ListSelectionListener() {
     
    				@Override
    				public void valueChanged(ListSelectionEvent e) {
    					System.out.println(es.getSelected());
     
    				}
    			});
     
    			es.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    			tCodePostaux.setSelectionModel(es);
     
    			//END <<  tCodePostaux
    			//START >>  btOK
    			btOK = new JButton();
    			btOK.addActionListener(new ActionListener() {
     
    				@Override
    				public void actionPerformed(ActionEvent e) {					
    					selectedCP = es.getSelected();
    					dispose();					
    				}
    			});
    			getContentPane().add(btOK, new CellConstraints("5, 7, 1, 1, fill, default"));
    			btOK.setText("OK");
    			//END <<  btOK
    			//END <<  jscp
    			//END <<  this
    			pack();
    			getRootPane().setDefaultButton(btOK);
     
    		} catch (Exception e) {
    			e.printStackTrace();
    			JOptionPane.showMessageDialog(this.getParent(), "Impossible de récupérer les données. Veuillez vérifier la connection avec le serveur", "Erreur de connection", JOptionPane.ERROR_MESSAGE);
    		}
    	}
     
    	private List<CodePostal> getData() throws Exception{		
    		currentSession.beginTransaction();
    		List<CodePostal> data = currentSession.createCriteria(CodePostal.class).add(Restrictions.sqlRestriction("id_secteur is null")).addOrder(Order.asc("code")).list();
    		currentSession.getTransaction().commit();
    		return data;
    	}
     
    	public static List<CodePostal> getCP(JFrame parent) {
    		selectedCP = null;
    		CodePostalDialog me = new CodePostalDialog(parent, true);
    		me.setLocationRelativeTo(null);
    		me.setVisible(true);		
    		return selectedCP;			
    	}
     
    }
    La fonction getData() récupère les données sous forme de List, et le tout est transformé en GlazedList. J'ai commenté cette partie du code qui n'est peut-être pas claire pour quelqu'un qui n'utilise pas ces listes.

    La fonction getData() met une seconde à s'exécuter. Le reste du temps (quelques secondes) est pris pour l'affichage de la première "page".
    Ensuite dès que je bouge le curseur de scroll je suis reparti pour quelques secondes avant d'afficher le résultat et dans la console je vois bien qu'Hibernate effectue plusieurs selects.

    J'ai aussi un peu fait le bourrin dans le sens où dans la colonne Ville j'affiche directement une liste de villes (donc une List classique et son toString() par défaut qu'on reconnait avec les crochets qui englobent les villes affichées).

  5. #5
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Ce qui m'étonne c'est que tu explose les temps de chargement avec seulement 2000 villes et que le chargement de seulement un 30 code postaux en lazy (ce qui est affiché à l'écran) mette 5-6 secondes. Quelle est la base de donnée derrière? Faire une requetes sql renvoyant 10 villes ne devrais perndre qu'un dixaine de milliseconde. Multiplié par 23 codes postaux visible, ca nous amène à 230 milli secondes, siot 1/4 de seconde. Pas de quoi fouetter un chat :s

    Et charger 2000 villes sans le lazyn, ca devrais pas mettre plus d'une à deux secondes...

  6. #6
    Membre éclairé Avatar de Julien Bodin
    Homme Profil pro
    Devops
    Inscrit en
    Février 2009
    Messages
    474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Devops
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 474
    Par défaut
    @OButterlin : J'utilise la dernière version, la 3.3.2.GA

    @tchize_ : J'utilise une petite base mysql.

    J'ai effectué une mesure plus précise des temps, c'est plus bas que ce que je m'imaginais mais ça reste encore trop.
    En Lazy l'affichage de la jtable prend deux secondes, et chaque scroll reprend deux secondes.

    En non-lazy le chargement prend 7 secondes.

    Mais aujourd'hui mes conditions de travail sont un peu particulières puisque la boite dans laquelle je fais mon stage est fermée pendant trois semaines. Du coup je bosse en télétravail avec une machine plus puissante que là-bas et une base de donnée en local alors qu'elle est sur le réseau en temps normal.

    Je vous met la partie "intéressante" du log lorsque je suis en non-lazy, j'y connais pas grand chose en log Hibernate mais y'a peut-être quelque chose de choquant.
    Par contre ça fait 1Mo mais c'est très redondant : http://dl.free.fr/oAHDx1Jcm

  7. #7
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Je suis en train de télécharger tes logs, mais si tu a activé toutes les option de messages debug d'hibernante, il n'y a rien d'étonnant que ce soit lent. La génération des messages prend beaucoup de temps! Essaie déjà de les désactiver. 2000 rows récupérés d'une base mysql ne devrais pas prendre 7 secondes!

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

Discussions similaires

  1. Problème de performance avec LEFT OUTER JOIN
    Par jgfa9 dans le forum Requêtes
    Réponses: 6
    Dernier message: 17/07/2005, 13h17
  2. [jeu]problème de performance d'un algo
    Par le Daoud dans le forum Algorithmes et structures de données
    Réponses: 12
    Dernier message: 30/05/2005, 16h07
  3. [C#] Probléme de performance avec IsDbNull
    Par jab dans le forum Windows Forms
    Réponses: 8
    Dernier message: 04/04/2005, 11h39
  4. [oracle 9i][Workbench]Problème de performance
    Par nuke_y dans le forum Oracle
    Réponses: 6
    Dernier message: 03/02/2005, 17h38
  5. [ POSTGRESQL ] Problème de performance
    Par Djouls64 dans le forum PostgreSQL
    Réponses: 6
    Dernier message: 26/05/2003, 16h18

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