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

JDBC Java Discussion :

PreparedStatement lenteur impressionnante


Sujet :

JDBC Java

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 139
    Points : 124
    Points
    124
    Par défaut PreparedStatement lenteur impressionnante
    Salut à tous,

    J'ai un problème de BDD à traiter sur de gros volumes de données...

    En gros, en entrée j'ai un fichier que sur lequel j'effectue un traitement, pour stocker en bases les éléments. Il peut y avoir de 0 à n lignes, voici 2 traces d'exécutions pour un fichier de 1,10 Mo :

    Trace 1
    Nombre de lignes traitées : 19427
    [DEBUG] Fin de lecture, durée=437

    Trace 2
    Nombre de lignes traitées : 19427
    [DEBUG] Fin de lecture, durée=13968
    La trace 1 traite tout le fichier mais la ligne m_statementPreCreateDataLine.executeUpdate(); est mise en commentaire...

    La seconde effectue la sauvegarde en base... Imaginez ma stupeur lorsque j'ai essayé sur un fichier de 80 Mo pour le temps de traitement interminable...

    J'ai une classe qui crée un thread l'initilise et joue avec les méthodes start stop et save trame (cf. source ci dessous pour celle ci)

    source abbrégé :

    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
    class ThreadSaveData extends Thread implements Constantes
    {
    	private static PreparedStatement m_statementPreCreateDataLine ; // prépare le format de la ligne de données
     
    	public ThreadSaveData(Connection p_bddConnexion,String p_strNomTableData)
    	{
    		try {
    			m_statementPreCreateDataLine = p_bddConnexion.prepareStatement("INSERT INTO "+p_strNomTableData+" VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
    		} catch (SQLException e) {
    			System.err.println("erreur de préparation du statement dans le thread");
    			e.printStackTrace();
    		}
    	}
     
    	public void saveTrame(int p_iType, ArrayList p_tEltTable)
    	{
    		try {
     
    			m_statementPreCreateDataLine.setString(g_bddTableData.m_iColTemps, (String)p_tEltTable.get(0));
     
    			// ... etcc ...
     
    			String data = "" ;
    			Integer val = new Integer((String)p_tEltTable.get(5));
     
     
    			for (int cpt=0 ; cpt < val  ; cpt++)
    			{
    				data += (String)p_tEltTable.get(6+cpt) ;
    				if (cpt!=(val-1)) data += ".";
    			}	
     
    			m_statementPreCreateDataLine.setString(g_bddTableData.m_iColData, data);
     
    			m_statementPreCreateDataLine.executeUpdate();
     
    		} catch (SQLException e) {
    			System.err.println("erreur remplissage de statement");
    			e.printStackTrace();
    		}
    	}
    }

    Y a t il un moyen de résoudre cette lenteur ?? Merci d'avance pour votre aide

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Il ne faut pas utiliser l'opérateur + sur les String dans une boucle !!!

    Et évite les comparaisons entre Integer et int car cela implique une conversion implicite... (ce n'est pas couteux mais dans un boucle cela peut le devenir).

    Remplace ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        String data = "" ;
        Integer val = new Integer((String)p_tEltTable.get(5));
     
     
        for (int cpt=0 ; cpt < val  ; cpt++)
        {
            data += (String)p_tEltTable.get(6+cpt) ;
            if (cpt!=(val-1)) data += ".";
        }
    Par ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        StringBuffer buffer = new StringBuffer();
        int val = Integer.parseInt((String)p_tEltTable.get(5));
     
     
        for (int cpt=0 ; cpt < val  ; cpt++) {
            buffer.append( (String)p_tEltTable.get(6+cpt) );
            if (cpt!=(val-1)) {
                buffer.append( "." );
            }
        }
        String data = buffer.toString();
    }
    a++

  3. #3
    Membre habitué
    Inscrit en
    Juillet 2004
    Messages
    152
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 152
    Points : 173
    Points
    173
    Par défaut
    JDBC n'est pas forcément en cause dans cette histoire...
    Ca peut très bien provenir de ton SGBD. Si tu as un nombre important de contraintes ou d'index définis sur la table, cela peut fortement ralentir le temps de réponse en cas d'insert.

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 139
    Points : 124
    Points
    124
    Par défaut
    salut adiGuba !

    Mais comment je peux expliquer le temps multiplié par xx lorsque j'effectue cette action :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m_statementPreCreateDataLine.executeUpdate();
    bon ok il s'agit d'une insertion en base fois le nombre de ligne mais quand même ! ca paraît énorme !

    je comprends pas du tout

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 139
    Points : 124
    Points
    124
    Par défaut
    Voici la requête de création de la table. Un fichier -> un id d'où le id_xx ...

    Pour ce qui est des champs text pour un id ou autre je traite du texte alors j'ai stocké ca en texte à voir si ca serai plus rapide en les convertissant...

    Code coupé mais il y a 8 colonnes au format "text"

    CREATE TABLE data_file_id_1
    (
    temps text,
    // ....
    commentaire text
    )
    WITHOUT OIDS;
    ALTER TABLE data_file_id_1 OWNER TO softOwner;

  6. #6
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par WuKoDLaK
    Mais comment je peux expliquer le temps multiplié par xx lorsque j'effectue cette action :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m_statementPreCreateDataLine.executeUpdate();
    Oups je n'avais pas vu que la différence venait de la mise en commentaire de l'update...


    Essaye déjà d'envoyer une requête identique via les commandes SQL de ta base, pour voir si le problème est reproduisible ou pas...

    a++

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 139
    Points : 124
    Points
    124
    Par défaut
    Pour information, ne sachant pas si cela à de l'importance ou non, j'utilise une base type Postgre SQL ....

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 139
    Points : 124
    Points
    124
    Par défaut
    On dirai limite un problème exponentiel...

    [DEBUG] Début de la lecture
    [INFO] Avec enregistrement en base
    Nombre de lignes traitées : 390374
    [DEBUG] Fin de lecture, durée=271703 ms



    [DEBUG] Début de la lecture
    [INFO] Sans enregistrement en base
    Nombre de lignes traitées : 390374
    [DEBUG] Fin de lecture, durée=5437 ms

  9. #9
    Membre éprouvé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    652
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2002
    Messages : 652
    Points : 1 151
    Points
    1 151
    Par défaut
    Si tu veux gagner du temps et si ton traitement le permet, passe en mode autocomit false avant tes itérations et comit à la fin, gain de performances assuré !!!

    Je me fabrique régulièrement des injecteurs pour faire des tests de performances en situation critique (plusieurs milions d'enregistrements dans mes tables) et je n'ai pas de soucis de performance sur cette injection !



    En synthèse
    • c autocommit à false
    Clic me...
    CV en ligne

    Il y a 10 types de personnes, celui qui connait le binaire, et l'autre...

    Pas de réponse en MP...Merci

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 139
    Points : 124
    Points
    124
    Par défaut
    Bon j'ai trouvé une solution qui diminue le temps .... considérablement !!!! voir ci dessous...

    Nombre de lignes traitées : 19427
    [DEBUG] Fin de lecture, durée=13953

    Nombre de lignes traitées : 19427
    [DEBUG] Fin de lecture, durée=5516
    Explication :
    -----------

    http://jguillard.developpez.com/JDBC/10.html



    Y a t il mieux ?? lol je ne sais pas mais c'est déjà énorme ...

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 139
    Points : 124
    Points
    124
    Par défaut
    Citation Envoyé par Alwin
    Si tu veux gagner du temps et si ton traitement le permet, passe en mode autocomit false avant tes itérations et comit à la fin, gain de performances assuré !!!

    Je me fabrique régulièrement des injecteurs pour faire des tests de performances en situation critique (plusieurs milions d'enregistrements dans mes tables) et je n'ai pas de soucis de performance sur cette injection !



    En synthèse
    • c autocommit à false

    héhé merci à toi !!! juste je venais de trouver le tuto indiqué plus haut ... ! j'avou que j'aurais pas pensé à ce genre de truc...

Discussions similaires

  1. Réponses: 30
    Dernier message: 09/02/2009, 15h57
  2. [Débutant] Lenteur avec TComPort
    Par PhDt76 dans le forum C++Builder
    Réponses: 22
    Dernier message: 27/09/2003, 21h43
  3. lenteur d'affichage de requete dans un DBGrid
    Par nico27 dans le forum InterBase
    Réponses: 9
    Dernier message: 23/06/2003, 13h54
  4. [Sybase]probleme de lenteur
    Par MASSAKA dans le forum Sybase
    Réponses: 3
    Dernier message: 19/03/2003, 22h58
  5. Lenteur d'execution de Jbuilder 6
    Par Tsimplice dans le forum JBuilder
    Réponses: 6
    Dernier message: 18/12/2002, 14h41

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