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 :

Lenteur écriture de fichier (JDBC)


Sujet :

JDBC Java

  1. #1
    Membre régulier
    Inscrit en
    Mars 2005
    Messages
    319
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 319
    Points : 80
    Points
    80
    Par défaut Lenteur écriture de fichier (JDBC)
    Salut,

    J'utilise jdbc pour ramener le résultat d'une requête et l'écrire dans un fichier.
    Je viens de faire un test avec une table contenant 5 millions de lignes et c'est extrêmement long.

    Je fais ceci pour écrire mon fichier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    while (rs.next()) {
    String line = "";
    for(int j = 1; j <= nbcol; j++){
    line = line + rs.getString(j) + ";";	
    }
    line = line.substring(0,line.length() - 1);
    file_w.write(line);	
    }
    file_w.close();
    Une fois le recordset rempli,
    je boucle dessus.
    La variable line me permet de concaténer les colonnes et de mettre un séparateur(.

    J'ai fait un test en mettant une showMessageDialog juste avant le while afin de voir si c'était le select ou l'écriture qui mettait du temps.
    Résultat, la showMessageDialog affiche un message en moins d'une minute.
    C'est donc l'écriture qui met du temps.

    Existe-il une façon plus optimal d'écrire?
    Peut-être que je m'y prends mal ?

    Merci pour votre aide.

  2. #2
    Expert éminent sénior
    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 : 45
    Localisation : Belgique

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Déjà, on ne concatène pas les String dans une boucle, c'est extrèmement couteux

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    while (rs.next()) {
      StringBuilder line = new StringBuilder();
      for(int j = 1; j <= nbcol; j++){
         line.append(rs.getString(j)).append(';');	
      }
      line.setLength(line.length()-1);
      file_w.write(line);	
    }
    file_w.close();
    Ensuite, non, le close() ne devrais pas être long. Montre nous le code qui fait la mesure de temps et son résultat.

  3. #3
    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,


    Perso dans ce cas là je me passerait même du StringBuilder. Autant écrire directement la ligne dans le fichier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	while (rs.next()) {
    		for (int j = 1; j <= nbcol; j++) {
    			if (j!=1) file_w.append(';');
    			file_w.append(rs.getString(j));
    		}
    	}


    Sinon, attention à bien fermer toutes les ressources (ResultSet, Writer, etc.) proprement, c'est à dire avec un try/finally par ressource ou le try-with-ressource de Java 7...



    a++

  4. #4
    Membre régulier
    Inscrit en
    Mars 2005
    Messages
    319
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 319
    Points : 80
    Points
    80
    Par défaut
    Pour mesurer en faite,
    je fais un println avant et après le executeQuery();
    et un autre avant la boucle while et après le close.

    Je viens de refaire un test avec ma méthode et le stringbuilder
    Pour 500 000 lignes :
    avec ma méthode :
    DEBUT RS TIME Sun Dec 29 11:35:50 CET 2013
    FIN RS TIME Sun Dec 29 11:35:53 CET 2013
    DEBUT ECRITURE TIME Sun Dec 29 11:35:53 CET 2013
    FIN ECRITURE TIME Sun Dec 29 11:36:41 CET 2013

    avec le stringBuilder :
    DEBUT RS TIME Sun Dec 29 11:44:41 CET 2013
    FIN RS TIME Sun Dec 29 11:44:42 CET 2013
    DEBUT ECRITURE TIME Sun Dec 29 11:44:42 CET 2013
    FIN ECRITURE TIME Sun Dec 29 11:45:29 CET 2013

    Pour 5 millions de lignes :
    avec ma méthode :
    DEBUT RS TIME Sun Dec 29 12:01:00 CET 2013
    FIN RS TIME Sun Dec 29 12:01:08 CET 2013
    DEBUT ECRITURE TIME Sun Dec 29 12:01:08 CET 2013
    FIN ECRITURE TIME Sun Dec 29 12:10:07 CET 2013

    avec le stringBuilder
    DEBUT RS TIME Sun Dec 29 11:47:07 CET 2013
    FIN RS TIME Sun Dec 29 11:47:09 CET 2013
    DEBUT ECRITURE TIME Sun Dec 29 11:47:09 CET 2013
    FIN ECRITURE TIME Sun Dec 29 11:55:34 CET 2013

    Je constate que les temps sont quasi identique,
    pour 500 000 entre 1min30 et 2min.
    Et pour 5 000 000 de lignes entre 8min et 9min.

    PS : j'ai pas reussi à le faire avec la 3ème méthode
    file_w.append(';');

  5. #5
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Citation Envoyé par Melvine Voir le message
    PS : j'ai pas reussi à le faire avec la 3ème méthode
    file_w.append(';');
    C'est quoi le type de ta variable file_w ? Ce n'est pas un Writer ?

    Pour la méthode avec StringBuilder, tu pourrais tenter de recycler le StringBuilder, ce qui ferait gagner du temps sur la gestion de tableaux internes (réservation, libération) : tu l'instancies en dehors de la boucle, et, à chaque nouvelle itération, tu fais line.setLength(0);

  6. #6
    Membre régulier
    Inscrit en
    Mars 2005
    Messages
    319
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 319
    Points : 80
    Points
    80
    Par défaut
    donc j'ai fait ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     StringBuilder line = new StringBuilder();
    while (rs.next()) {
     line.setLength(0); 
      for(int j = 1; j <= nbcol; j++){
         line.append(rs.getString(j)).append(';');	
      }
      line.setLength(line.length()-1);
      file_w.write(line);	
    }
    file_w.close();
    Et j'obtiens ces temps :

    Pour 500 000 de lignes :
    DEBUT ECRITURE TIME Sun Dec 29 15:09:18 CET 2013
    FIN ECRITURE TIME Sun Dec 29 15:09:27 CET 2013

    Donc seulement 9 secondes!

    Pour 5 millions de lignes :
    avec ma méthode :
    DEBUT ECRITURE TIME Sun Dec 29 15:10:58 CET 2013
    FIN ECRITURE TIME Sun Dec 29 15:13:08 CET 2013

    Je passe de 9 minutes à 2minutes et 10 secondes (un fichier de 1.3 Go).

    Merci beaucoup pour ton astuce , je bats tous les records!

  7. #7
    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
    Supprimes le StringBuilder et tu gagneras encore.
    Il est inutile d'écrire dans le StringBuilder pour ensuite écrire la même chose dans le fichier.

    Autant écrire directement dans le fichier...

    Ca peut sembler anecdotique mais sur 5 millions de ligne ca peut jouer


    a++

  8. #8
    Membre régulier
    Inscrit en
    Mars 2005
    Messages
    319
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 319
    Points : 80
    Points
    80
    Par défaut
    je viens de tester sans le stringbuilder,
    j'ai fait ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    while (rs.next()) {
    for(int j = 1; j <= nbcol ; j++){
    if (j!=1) file_w.write(";");
    file_w.write(rs.getString(j));	
    }
    file_w.write("\n");
    }
    file_w.close();
    pour 5 millions de lignes,cela a pris 10 minutes.

    Après peut-être que je m'y prend mal.

  9. #9
    Expert éminent sénior
    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 : 45
    Localisation : Belgique

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    file_w est de quel type? C'est bien un bufferedwriter?

  10. #10
    Membre régulier
    Inscrit en
    Mars 2005
    Messages
    319
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 319
    Points : 80
    Points
    80
    Par défaut
    déjà je tenais à dire que je suis satisfait des temps avec le stringbuilder.
    Si je peux faire mieux , why not.

    file_w c'est une classe que j'ai crée et qui possède une méthode write :



    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
     
    public class file_w{
     
    FileWriter writer = null;
     
    public void write(String var){		
    	try
    	{
            writer.append(var);
           // writer.append("\n");
            writer.flush();
    	}
    	catch(IOException e)
    	{
    	     e.printStackTrace();
    	} 
        }

  11. #11
    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 Melvine Voir le message
    file_w c'est une classe que j'ai crée et qui possède une méthode write :
    Et qui sert à quoi ??? A cacher les exceptions ?
    C'est super-crade çà !!!



    Sinon le flush() est inutile dans ton cas (sauf à la toute fin du traitement), et comme l'indique tchize_, le BufferedWriter est de rigueur...


    a++

  12. #12
    Membre régulier
    Inscrit en
    Mars 2005
    Messages
    319
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 319
    Points : 80
    Points
    80
    Par défaut
    de ce que j'avais compris des tutos java.
    Tu dois créer des classes avec des méthodes en fonction de tes besoins.

    J'ai créer une classe pour le traitement des fichiers
    avec des méthodes
    open
    read
    write
    close
    et j'appelle cette classe dans ma classe qui exécute le sql.

    Je n'utilisait pas de BufferedWriter, je viens de l'intégrer au code.
    ça ne change pas grand chose.
    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
     
    public class file_w{
     
    	FileWriter writer = null;
    	BufferedWriter bw = null;
     
    	public void open(String fichier) {		
    		try
    		{
    		     writer = new FileWriter(fichier);
    		     bw = new BufferedWriter(writer);
    		}
    		catch(IOException e)
    		{
    		     e.printStackTrace();
    		} 	 
    	}     
     
    public void write(StringBuilder var){		
    	try
    	{
            bw.append(var);
            bw.append("\n");
    	}
    	catch(IOException e)
    	{
    	     e.printStackTrace();
    	} 
        }

  13. #13
    Expert éminent sénior
    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 : 45
    Localisation : Belgique

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Soit tu utilise des stringbuilder (comme tu l'a fait au début et qui te satisfait), soit tu utiliser un bufferedWriter. Mais les deux ensemble, c'est pas très utile, voir contre performant. Du coup, je suis étonné de voir cette méthode write qui prendre un StrungBuilder alors que la version précédente prennait un String :/



    Et je suis du même avis que adiguba, cette classe ne sert à rien, à part à crader le code....

  14. #14
    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 Melvine Voir le message
    de ce que j'avais compris des tutos java.
    Tu dois créer des classes avec des méthodes en fonction de tes besoins.

    J'ai créer une classe pour le traitement des fichiers
    avec des méthodes
    open
    read
    write
    close
    et j'appelle cette classe dans ma classe qui exécute le sql.
    Sauf que ta classe se contente de reproduire les méthodes d'un Writer, ce qui n'est pas très utile (et qui nous as induit en erreur).

    La seule différence c'est que tu "caches" les exceptions, ce qui n'est pas vraiment conseillé car cela peut engendrer d'autre problème...




    a++

  15. #15
    Membre régulier
    Inscrit en
    Mars 2005
    Messages
    319
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 319
    Points : 80
    Points
    80
    Par défaut
    tchize_ en faite , comme j'ai utilisé un stringbuilder,
    du coup ma classe write qui prenait du départ un String en paramètre ne fonctionnait plus donc j'ai changé avec un Stringbuilder.

    adiGuba, je comprends mieux, en faite si la classe java existe déjà et que je ne fais pas de modification dessus, je peux l'utiliser directement dans mon code.Car si je créer une classe qui se contente uniquement d'utiliser une classe java, c'est inutile et ça peut être dangereux car je n'aurai pas les exceptions.
    Je ne créer de classe que si je fais un développement spécifique.

    En tout cas, merci à vous.

Discussions similaires

  1. Réponses: 26
    Dernier message: 25/04/2007, 17h04
  2. Réponses: 2
    Dernier message: 29/05/2006, 09h54
  3. [VB.NET]Problème de lecture et écriture sur fichier texte
    Par zouhib dans le forum Windows Forms
    Réponses: 25
    Dernier message: 23/05/2006, 15h30
  4. Readdir et écriture de fichiers
    Par Soum dans le forum C
    Réponses: 6
    Dernier message: 09/01/2006, 16h36
  5. Réponses: 2
    Dernier message: 15/11/2005, 09h58

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