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 :

problème de Heap Space - Peut-on vider la mémoire lors du parcours d'un ResultSet ?


Sujet :

JDBC Java

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2014
    Messages : 16
    Points : 6
    Points
    6
    Par défaut problème de Heap Space - Peut-on vider la mémoire lors du parcours d'un ResultSet ?
    Bonjour à tous,

    Je dois faire une requête sur une table Oracle de 165.000.000 de lignes, l'objectif étant de mesurer le temps mis par la requête (le résultat n'est pas important et n'est bien sur pas affiché).
    Cela fonctionne si je fais un Select max(champ1) from source; car mon ResultSet ne me renvoie qu'une valeur mais je ne sais pas comment gérer une requête de type Select champ1 from source;.
    Pour que ma requête soit effective et que le SGBD parcoure la table, je fais un resultset.last(); et j'ai une erreur de type java heap space (ou garbage collector overhead limit) à partir de 2.5 millions de lignes.

    J'ai modifié les paramètres -Xms et -Xmx au niveau du fichier eclipse.ini ou dans les paramètres Java de Windows mais je suis très loin du compte.
    Je voulais donc savoir si il était possible de vider (en partie ?) la mémoire qui se remplit lors d'un ResultSet ?
    Sachant que c'est un curseur, j'ai l'impression qu'il enregistre en mémoire des informations dès que je le bouge et, dès lors, j'imagine qu'il est possible de vider cette mémoire.

    J'ai modifié la valeur du Fetch (100, 500, 1000) ce qui modifie les quantités de données que gère le driver mais cela ne résout pas mon problème.
    Souhaitant avoir le résultat exact de la requête, je ne peux pas "découper" celle-ci en plusieurs sous-requêtes (de 0 à 2 millions, de 2 à 4 millions, ...)

    Code de création du Resultset :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    PreparedStatement ps=conn.prepareStatement(request, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
    ...
    ResultSet rs = ps.executeQuery();
    ...
    rs.last();
    Merci de votre aide !
    (Je suis débutant en Java, merci de pardonner des erreurs ou des oublis de ma part)

  2. #2
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Points : 1 993
    Points
    1 993
    Par défaut
    Tu veux quoi précisement?
    Le temps d'exécution de la requête? Le nombre de résultats?

    Parce que techniquement, à partir du moment où tu arrives au premier rs.next, ta requête a terminé de s'exécuter.
    Donc si c'est effectivement ça, ben voilà... Tu as déjà réussi, tu n'as pas besoin de parcourir les infos pour avoir plus d'infos

    Détail cependant : les requêtes sont la plupart du temps optimisées par le SGBD, donc deux requête identiques ne donneront pas toujours le même résultat. Le seul moyen de connaitre le coût d'une requête est d'étudier son plan d'exécution
    Je ne suis pas mort, j'ai du travail !

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2014
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Je m’intéresse au temps pris par la requête comme si celle-ci s'effectuait directement à partir de la base (donc complètement d'où le rs.last() )
    En fait, je génère, récupère et analyse le fichier trace d'Oracle et je récupère une valeur bien précise de celui-ci (elapsed time).
    Il me faut donc avoir la requête qui s'effectue complètement.

    Mais, je me demande si je pars de la bonne façon. Si je fais un resultset.last() il y aura 165 millions de connexions entre mon appli et la base Oracle ? et du coup le résultat du fichier Trace sera biaisé ?

    Si c'est le cas, je dois peut-être oublier JDBC ? et passer par des scripts sur la machine distante contenant la base ...

  4. #4
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Points : 1 993
    Points
    1 993
    Par défaut
    Citation Envoyé par baba63 Voir le message
    Je m’intéresse au temps pris par la requête comme si celle-ci s'effectuait directement à partir de la base (donc complètement d'où le rs.last() )
    Complètement pour toi, c'est le temps pris par la base pour exécuter la requête, ou le temps pour l'exécuter et parcourir l'intégralité des résultats? Avec un scrollable resultset, quand tu fais un rs.last, il se positionne sur le dernier enregistrement, normalement il ne lit pas toutes les valeurs (avec le driver Oracle du moins, MySQL renvoie tout...)

    Le elapsed time d'une requête est le temps de parcours et de création des résultats, une fois que le premier résultat arrive, la requête est considérée comme terminée quel que soit le temps que tu passes à le parcourir.

    Enlève le scrollable (TYPE_SCROLL_INSENSITIVE) qui ne te sert à rien si tu veux juste faire un last : si tu n'as que besoin d'aller à la fin sans revenir en arrière ça devrait être suffisant
    Je ne suis pas mort, j'ai du travail !

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2014
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Merci de ton aide eulbobo

    " c'est le temps pris par la base pour exécuter la requête, ou le temps pour l'exécuter et parcourir l'intégralité des résultats? "
    Pour moi, c'est la même chose mais visiblement, il doit me manquer des fondamentaux sur les bases de données.
    Je voudrais simuler le comportement de la base lorsqu'un utilisateur lance une requête "select champ1 from source;"

    Lorsque je me positionne sur un enregistrement assez distant, cela prend du temps (environ 8-10 secondes pour arriver à un million d'enregistrement) que je fasse des resultset.next() jusqu'a while (rs.getRow()<1000000) ou directement rs.absolute(1000000); (à vue d’œil, le comportement semble identique)
    Je pensais qu'il lisait les valeurs mais c'est vrai que cela ne correspond pas.
    Quand je fais cette requête sur la base, je mets environ 45 minutes et 10s*165 ne font pas 45 minutes.
    Il doit y avoir un enregistrement des informations quelque part tout de même car j'ai un problème de heap space.

    "Le elapsed time d'une requête est le temps de parcours et de création des résultats, une fois que le premier résultat arrive, la requête est considérée comme terminée quel que soit le temps que tu passes à le parcourir"

    Merci pour tes explications, je me prenais la tête depuis deux jours pour parcourir la table alors que je n'en ai pas besoin.
    Un resultset.next suffira donc !

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2014
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    En fait, après vérifications, si je fais juste une requête select champ from source; et que j'utilise rs.next(); au lieu de rs.last(); , j'obtiens un elapsed time de 0 alors qu'il est de 9 pour la même requête avec un rs.last() lorsque cela plante vers 2,5 millions de lignes lues.

    Après, je ne sais pas comment est construite la base, il y a peut-être un comportement spécifique.

    De toutes façons, il faudra que je récupère das le futur, d'autres résultats du fichier trace et du coup, je reviens sur la question de départ et le fonctionnement du resultset.
    Qu'est ce qui est enregistré en mémoire ? Peut-on vider cette mémoire ?
    Faut-il éviter d'utiliser JDBC pour un tel cas ?

  7. #7
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Points : 1 993
    Points
    1 993
    Par défaut
    Alors reprenons du début

    D'où tu sors ton elapsed time?
    C'est quoi ta base précisement?
    C'est quoi ton driver de connexion?
    C'est quoi ton code complet?

    Il n'y a pas de raisons que tu ne puisses pas le faire en JDBC. Par contre je le répète, tu as l'air de vouloir faire des outils de suivi du temps de traitement qui sont la plupart du temps déjà présents dans les outils des DBA.
    Si l'idée est de faire de l'optimisation, il faut passer par le plan d'exécution
    Je ne suis pas mort, j'ai du travail !

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2014
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Bon, je fais actuellement une interface web de benchmarking pour des chercheurs en informatique. Ce que je veux faire, c'est permettre à des utilisateurs qui utiliseraient cette interface de se connecter en SSH sur un réseau et envoyer des requêtes sur des bases de données (pour l'instant Postgres et Oracle) situées sur des machines virtuelles qu'ils auraient construites.
    Ces utilisateurs pourraient dans l'idéal indiquer des paramètres (fetch, sdu, send buffer, ...) envoyer une requête (en différé, en obtenant un résultat moyen, ...) et obtenir un (voire plusieurs) résultats liés au temps d’exécution de la requête.
    Le but étant de générer des graphiques à partir des résultats (axe du temps en ordonnée et requêtes ou valeur des paramètres en abscisses).

    Là, je bloque sur la demande d'une personne qui souhaite obtenir l'elapsed time du fichier trace généré lors d'une requête "select champ1, champ2, champ3 from source;".
    Donc, en fait, je n'ai pas construit la base, ce chercheur m'a donné une copie de sa VM (avec qq paramètres modifiés). C'est une base Oracle11G installée sur une version ubuntu 12.4 desktop (version precise je crois).
    N'y connaissant rien à Oracle, j'ai juste étudié le fonctionnement des outils de traçage.
    J'envoie donc à partir de mon appli des commandes en SSH directement sur les machines permettant de générer un fichier trace, de le convertir en texte avec tkprof, de le parser et de récupérer ce fameux elapsed time (le temps total de la colonne elapsed) pour la séquence correspondant à ma requête.
    Tout marchait bien quand mes requêtes se limitaient à "select max(champ1) from source;" et maintenant, génération d'erreurs...
    Le but n'est pas de réinventer la roue mais d’accélérer le travail des chercheurs, qu'ils ne s'embêtent pas à récupérer des infos à droite, à gauche, puis de construire des graphiques avec Excel mais d'automatiser ces tâches fastidieuses.

    Le driver Oracle que j'utilise est ojdbc6_g.jar

    Pour ce qui est du code, voilà la fonction en question où j'appelle la requête, des paramètres de connexion (login, pwd, ...) de requêtes (select, from condition, ...) et de paramètrages (fetch, sdu, ...) sont envoyés :

    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
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    	@Override
    	public ResultDatas find(ConnectDatas connDatas, RequestDatas reqDatas, ParamDatas paramDatas)
    			throws SQLException, JSchException, ClassNotFoundException {
     
     
    		PreparedStatement ps = null;
    		ResultSet rs = null;
    		ResultDatas resultdatas = new ResultDatas();
    		int time = -1;
     
    		String request;
    		String reply = "";
    		String user_dump_dest="";
     
    		if (reqDatas.getCondition() == null) {
    			request = "SELECT " + reqDatas.getNb_datas() + " FROM "
    					+ reqDatas.getTable() + "--";
    		}
    		else
    		{
    			request = "SELECT " + reqDatas.getNb_datas() + " FROM "
    					+ reqDatas.getTable() + " "+ reqDatas.getCondition()
    					+ "--";
    		}
     
     
    		System.out.println("QUERY : "+request);
     
    		ConnectJDBCOracle connJdbcORA=new ConnectJDBCOracle();
     
    		Connection conn = connJdbcORA.getInstance(connDatas, paramDatas);
     
    		conn.setAutoCommit(false);
     
     
    		if ((paramDatas.isTrace()==true)  && ((reqDatas.getResultime().equals("Elapsed Time")) || (reqDatas.getResultime().equals("CPU Time"))))
    				{
    					PreparedStatement ps_alter_trace=null;
    					PreparedStatement ps_alter_timed=null;
    					PreparedStatement ps_alter_identifier=null;
    					PreparedStatement ps_traceonly=null;
     
     
    					ps_alter_trace=conn.prepareStatement("alter session set sql_trace=true --");
    					ps_alter_trace.executeQuery();
    					ps_alter_trace.close();
     
    					ps_alter_timed=conn.prepareStatement("alter session set timed_statistics=true --");
    					ps_alter_timed.executeQuery();
    					ps_alter_timed.close();
     
    					ps_alter_identifier=conn.prepareStatement("alter session set tracefile_identifier=BDB --");
    					ps_alter_identifier.executeQuery();
    					ps_alter_identifier.close();
     
     
    					System.out.println("set sql_trace=true; // set timed_statistics=true; // set tracefile_identifier=BDB;");
     
     
    				}
     
    		ps=conn.prepareStatement(request,
    				ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);		
    		System.out.println("connection succeed");
     
     
    		// Modify fetch 
    		if (paramDatas.getFetch()!=-1)
    		{
    			ps.setFetchSize(paramDatas.getFetch());
    			//rs.setFetchSize(paramDatas.getFetch());
    			System.out.println("Modif Fetch");
    		}	
     
    		// measure of request time
    		long time_begin = System.currentTimeMillis();
     
     
    		rs = ps.executeQuery();
     
    		//rs.setFetchSize(paramDatas.getFetch());
     
     
    		int cursor=ps.getFetchSize();
    		int cpt=0;
     
    		rs.next();
     
     
    //			while (rs.getRow()<1000000)
    //				{rs.next();}
    //				System.out.println("1 million");
    //				
    //			while (rs.getRow()<2000000)
    //				{rs.next();}	
    //				System.out.println("2 million");
    //				
    //			while (rs.getRow()<3000000)
    //			{rs.next();}	
    //			System.out.println("3 million");
     
    //			while (!rs.last())
    //			{rs.next();}
    //			
    //			
    //			if (rs.isLast())
    //			{
    //				System.out.println("fini");
    //			}
     
    //				System.out.println("Valeur curseur "+cursor);
    //				cpt++;
    //
    //				rs.absolute(cursor);
    //				
    //				cursor=cursor+ps.getFetchSize();
    //				System.out.println("cpt :"+cpt);
     
     
     
    		//connjdbc.close();
    		long time_end = System.currentTimeMillis();
     
    		System.out.println("FETCH ORA JDBC :"+rs.getFetchSize());
     
     
    	   ResultSetMetaData rsmd = rs.getMetaData();
    	   System.out.println("rsmd = rs.getMetaData()");
    		int nb_col = rsmd.getColumnCount();
    		 System.out.println("rsmd = rs.getColumnCount()");
    		time = (int) (time_end - time_begin);
     
    		System.out.println("time = (int) (time_end - time_begin);" );
     
     
    		if (reqDatas.isPostscreen() == true)
    		{
    			System.out.println("postscreen");
    			JavaTreatment treatJava = new JavaTreatment();
    			reply = treatJava.writeJava(rs);
    		}
     
    		if (reqDatas.isJsonfile() == true) {
    			System.out.println("jsonfile");
    			rs.first();
    			JsonTreatment treatJson = new JsonTreatment();
    			treatJson.writeJson(rs);
    		}
     
     
     
    		long nbdatas=0;
     
     
    //		rs.last();
    //		System.out.println("rs.last");
    //		long nbdatas = rs.getRow();
     
     
     
    		System.out.println("Java time = " + time);
     
    		if ((paramDatas.isTrace()==true) && (reqDatas.getResultime().equals("Elapsed Time")))
    		{
    			user_dump_dest="/opt/oracle/Oracle11gee/diag/rdbms/orcl/orcl/trace";
    			time=retrieveTraceTime(connDatas,reqDatas.getNb_datas(), user_dump_dest);
    			System.out.println("DAOGenericOra Time : retrieveTraceTime");
    		}
    		else
    		if ((paramDatas.isTrace()==true) && (reqDatas.getResultime().equals("CPU Time")))
    		{
    			user_dump_dest="/opt/oracle/Oracle11gee/diag/rdbms/orcl/orcl/trace";
    			time=retrieveTraceTime(connDatas,reqDatas.getNb_datas(), user_dump_dest);
    			System.out.println("DAOGenericOra Time : retrieveTraceTime");
    		}	
    		else
    		if ((paramDatas.isTrace()==true) && (reqDatas.getResultime().equals("Total Time")))
    		{
    			user_dump_dest="/opt/oracle/Oracle11gee/diag/rdbms/orcl/orcl/trace";
    			time=retrieveTraceTime(connDatas,reqDatas.getNb_datas(), user_dump_dest);
    			System.out.println("DAOGenericOra Time : retrieveTraceTime");
    		}		
    		else	
    		{
    			time = (int) (time_end - time_begin);
    			System.out.println("DAOGenericORA Time : JavaTime");
    		}
     
    		resultdatas.setName_table(reqDatas.getTable());
    		resultdatas.setColumns(nb_col);
    		resultdatas.setReply(reply);
    		resultdatas.setRows(nbdatas);
    		resultdatas.setRequestTime(time);
     
    		}
     
     
     
    		connJdbcORA.close();
    		System.out.println("Method DAOGenericORA.find() finish");
    		return resultdatas;
    	}
    Désolé pour le code qui est un peu moche, je fais pas mal de test dessus.

    Pour ce qui est des méthodes permettant de générer le fichier trace et de récupérer la valeur elapsed time :

    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
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
     
    /** This method allows to retrieve a specific time from the Oracle Trace file.<br/>
             * Commands are directly sent on the database with oracle user.<br/>
             * These commands correspond to 'find /../../trace_file_BDB.trc', 'tkprof /../../trace_file_BDB.trc ./javatrace.txt', 'cat javatrace.txt'  
             * 
             * @param rs
             * @return time from Execution Time
             * @throws SQLException 
             * @throws JSchException 
             * @throws ClassNotFoundException 
             */
    	public int retrieveTraceTime(ConnectDatas connDatas, String queryToFind, String trace_user_dump_dest) throws ClassNotFoundException, JSchException, SQLException
    	{
    		System.out.println("Method retrieveTraceTime");
    		int time=0;
    		//String trc_file="";
     
    		System.out.println("QueryToFind :"+queryToFind);
     
    		try {
    			ConnectSSH connssh = new ConnectSSH();
    			sessionSh = connssh.doRemoteConnection(connDatas.getLogin(), connDatas.getPwd(), connDatas.getSsh_host(), "oracle"
    					, "oracle", connDatas.getRemote_host());	
     
     
     
    			ConnectSSH connssh2 = new ConnectSSH();
    			String commandFind="find "+trace_user_dump_dest+"/*BDB*.trc";
    			//trc_file=connssh2.sendCommand(sessionSh, "find /opt/oracle/Oracle11gee/diag/rdbms/orcl/orcl/trace/*BDB*.trc");
    			trc_file=connssh2.sendCommand(sessionSh, commandFind);
     
    		//	System.out.println("trc_file :"+trc_file);
     
     
    			trc_file=trc_file.substring(0,trc_file.length()-2);
     
    			ConnectSSH connssh3 = new ConnectSSH();
    			String commandTkprof="tkprof "+trc_file+" ./javatrace.txt";
    			System.out.println("Commande tkprof : "+commandTkprof);
     
    			String tkprof=	connssh3.sendCommand(sessionSh,commandTkprof);
     
    			ConnectSSH connssh4 = new ConnectSSH();
    			String trace=connssh4.sendCommand(sessionSh, "cat javatrace.txt");
     
    			System.out.println(" cat javatrace "+trace);
     
    			time = retrieveElapsedTime(trace, queryToFind);
    			System.out.println("Le temps trouvé après opérations est :"+time);
     
    			ConnectSSH connssh5 = new ConnectSSH();
    			connssh5.sendCommand(sessionSh, "rm javatrace.txt");
     
    			ConnectSSH connssh6 = new ConnectSSH();
    			String commandRemoveTrc="rm "+trc_file;
    			System.out.println("Commande remove Trc "+commandRemoveTrc);
    			connssh6.sendCommand(sessionSh, commandRemoveTrc);
     
    //			ConnectSSH connssh7 = new ConnectSSH();
    //			connssh7.sendCommand(sessionSh, "alter session set sql_trace=false;");
     
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return time;
    	}
     
     
     
    	/** This method allows with the Oracle Trace file to retrieve the Elapsed time of the query <br/>
             * First, the trace file is parsed with searching the begin of the query 'select s.timeid, ...'<br/>
             * In a second time, line with 'elapsed' is searched and columns are counted until finding the word 'elapsed'<br/>
             * Finally, at the following line containing 'total', columns are counted and the corresponding time to 'elapsed' is retrieved.<br/>  
             * 
             * 
             * @param trace
             * @return - elapsed time from Oracle Trace file
             */
    	public int retrieveElapsedTime(String trace, String queryToFind)
    	{
    		int time=-1;
     
     
    		String line="";
     
    		int slashN=trace.indexOf("\n");
    		line=trace.substring(0, slashN);
     
    		while(! line.contains(queryToFind))
    				{
     
    					trace = trace.substring(slashN+1);
    					slashN=trace.indexOf("\n");
    					line=trace.substring(0, slashN);
    					System.out.println("Boucle infinie dans retrievElapsedTime !");
    				}
     
    		System.out.println("Query trouvée !");
     
    		while (! line.contains("elapsed"))
    				{
    					trace = trace.substring(slashN+1);
    					slashN=trace.indexOf("\n");
    					line=trace.substring(0, slashN);
    				}
     
    		System.out.println("Elapsed de query trouvée !");
     
    		int nbCol=0;
     
    		// Ici la première ligne du texte contient "elapsed"
    		slashN=line.indexOf("\n");
     
    		while (! line.startsWith("elapsed"))
    		{
    			//Elimination des espaces en début et fin de ligne
    			while (line.startsWith(" "))
    			{
    				line=line.trim();
    			}
     
    			//Recherche de l'espace suivant
    			int newIndex = line.indexOf(" ");
    			line= line.substring(newIndex);
    			line=line.trim();
    			nbCol++;
    			System.out.println("ligne "+line);
    			System.out.println("Nb Col ds boucle "+nbCol+ " //newIndex "+newIndex);
     
    		}
    		// la colonne est trouvée
    		System.out.println("NB colonne : "+nbCol);
     
    		// on cherche la ligne contenant total
    		slashN=line.indexOf("\n");
    		while (!line.contains("total"))
    		{
    			trace = trace.substring(slashN+1);
    			slashN=trace.indexOf("\n");
    			line=trace.substring(0, slashN);
     
    		}
     
    		for (int i=0;i<nbCol;i++)
    		{
    			line=line.trim();
    			int newIndex=line.indexOf(" ");
    			line=line.substring(newIndex);
    			line=line.trim();
    		}
     
    		int endIndex=line.indexOf("  ");
    		System.out.println("endindex = "+endIndex);
    		line=line.substring(0, endIndex);
     
    		String resultTime=line;
    		float floattime=Float.parseFloat(resultTime);
    		time=(int) Math.floor(floattime);
    		System.out.println("time "+time);
    		return time;
    	}
    Cela m'arrangerait énormément que ta définition de l'elapsed time de ce fichier trace soit bonne mais je n'arrive pas à retrouver ce fonctionnement dans la pratique et je ne vois pas ce qui plante dans ma démarche.

    Merci en tout cas de ton aide.
    Et désolé pour mon code qui doit faire saigner les yeux de tout bon développeur ...

  9. #9
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Points : 1 993
    Points
    1 993
    Par défaut
    Du coup un truc à essayer : ne pas déclarer de resultSet Scrollable, donc changer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ps=conn.prepareStatement(request, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)
    En ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ps=conn.prepareStatement(request)
    Et normalement, tu ne devrais plus avoir de problème avec le rs.last()

    Tes méthodes treatJava.writeJava(rs); et treatJson.writeJson(rs); elles font quoi?


    Pour aider la JVM, ce que tu peux faire c'est redécouper en méthodes ton code : à chaque sortie de méthode, tout ce qui n'est plus utilisé pourra être collecté.


    Sinon, autre détail, c'est que normalement toutes les données d'exécutions et les statistiques se trouvent aussi directement dans la base de données, dans les tables DBA, et sont accessibles par "simple" requêtes select plutôt que de se connecter en SSH et parser des fichiers
    Je ne suis pas mort, j'ai du travail !

  10. #10
    Futur Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2014
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Magique !!!

    Bon, je n'arrive pas encore à avoir un résultat complet sans plantage mais je peux aller beaucoup plus loin (environ 10 millions)
    Je dois faire des tests et je pense respecter un ordre précis vu que j'ai enlevé "ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY"

    La méthode writeJava me met en forme le résultat si je veux l'afficher (pas le cas ici). Elle prend le resultset et utilise un objet ResultSetMetaData pour retrouver les colonnes et placer des <br/> au bons endroits.

    La méthode writeJson me permet d'écrire le résultat dans un fichier JSon mais je pense que cette fonction ne sera jamais utilisée.

    Je vais suivre ton conseil sur le découpage de cette méthode principale.

    Pour ta dernière remarque sur les données d’exécution et statistiques, je suis parti sur cette méthode au début ; j'ai vu comment récupérer le "spid" mais je n'ai pas trouvé d'infos suffisamment claires pour moi pour savoir comment retrouver les bonnes tables. N'ayant jamais eu de formation Oracle, je me suis arraché les cheveux qq jours sur cette façon de faire puis je suis passé au parsing du fichier trace.
    Du coup, à moins que le chercheur en question ne me donne les requêtes sur un plateau, je pense que je vais rester la dessus ; de plus je vais surement devoir récupérer d'autres données dans ce fichier trace et sans doute des informations réseau (ds le futur).

    En tout cas, merci, je continue à travailler dessus et je te tiens au courant des avancées.
    Par contre, je ne comprends toujours pas le fonctionnement de ce ResultSet.
    Il garde des infos en mémoire lorsqu'il est scrollable mais aussi (moins?) lorsqu'il ne l'est pas ?

  11. #11
    Futur Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2014
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Nickel, tout marche comme sur des roulettes.
    Au final, si je comprends bien, le ResultSet est bien un pointeur qui ne garde rien de spécial en mémoire sauf si il est scrollable et dans ce cas des infos doivent être mises en cache quelque-part ce qui expliquait les erreurs sur le heap-space ou le garbage collector.

    Merci, eulbobo, tu me sauves mon WE

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par baba63 Voir le message
    Nickel, tout marche comme sur des roulettes.
    Au final, si je comprends bien, le ResultSet est bien un pointeur qui ne garde rien de spécial en mémoire sauf si il est scrollable et dans ce cas des infos doivent être mises en cache quelque-part ce qui expliquait les erreurs sur le heap-space ou le garbage collector.

    Merci, eulbobo, tu me sauves mon WE
    En fait, ca dépend de la DB, et du driver. Donc il faut toujours se référer à la doc du driver dans ce cas là. Tu as un certain controle via Statement.setFetchSize()

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

Discussions similaires

  1. Java heap space Exception, problème de mémoire
    Par Bobble dans le forum Servlets/JSP
    Réponses: 11
    Dernier message: 08/11/2010, 18h04
  2. Réponses: 10
    Dernier message: 25/08/2010, 21h07
  3. Problème mémoire Java heap space avec tableau et ArrayList
    Par phoenix420 dans le forum Collection et Stream
    Réponses: 45
    Dernier message: 22/06/2010, 10h01
  4. Problème avec le Java heap space
    Par Viscapon dans le forum JSF
    Réponses: 5
    Dernier message: 18/05/2009, 17h42
  5. problème heap space
    Par selmaK dans le forum Général Java
    Réponses: 3
    Dernier message: 17/04/2007, 02h43

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