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

Persistance des données Java Discussion :

Diviser le traitement d'une requête créant un trop gros resultSet (OutOfMemoryException)


Sujet :

Persistance des données Java

  1. #1
    Membre averti
    Avatar de Heavy Metal Hero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juin 2007
    Messages : 152
    Points : 333
    Points
    333
    Billets dans le blog
    13
    Par défaut Diviser le traitement d'une requête créant un trop gros resultSet (OutOfMemoryException)
    Bonjour,

    Je suis actuellement en train de résoudre un problème de type OutOfMemoryException dû à un trop gros resultSet.

    Afin de résumer le fonctionnement de mon application :

    On boucle dans JAVA pour accéder à différentes tables d'une base postgresql :
    - Une requête récupère les données de la table courante.
    - Le programme JAVA les ajoute dans un iterator et les trie en fonction de critères définis (par exemple la date).
    On écrit ensuite les données triée dans un fichier.

    Les éléments récoltés s'accumulent dans la heap, ce qui nous amène à un crash de l'application quand le nombre d'entrées des tables est trop important.

    J'ai imaginé plusieurs solutions pour résoudre cette erreur :

    - Augmenter la taille de la heap, mais étant donné que les donnée peuvent aller du simple au double, ça ne ferait que retarder le problème.

    - Ecrire dans le fichier au fur et à mesure, à la fin du traitement de chaque table, ainsi, le résultSet qui contient les données d'une seule table au lieu de 22, ne devient pas trop gros (on effectue par contre le traitement 22 fois au lieu de 1). Problème : Les lignes vont être triées d'abord par table dans le fichier final, puisqu'on écrit au fur et à mesure.

    - Créer une vue qui sélectionne les données de toutes les tables voulues et les diviser avec un select pour diviser le traitement en plusieurs blocs (et être capable de reprendre la recherche là ou on s'est arrêté) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    create view ll as select * from alert_event
    select * from (select *, ROW_NUMBER() over (order by time asc) as rn from ll) as t1 where rn >= 0 and rn < 50000
    La boucle exécuterait ensuite le select à nouveau pour rn >= 50000 et rn < 100000 et ainsi de suite jusqu'à la fin.
    Problème : quand on utilise plusieurs tables dans la vue, une erreur arrive car plusieurs tables ont les même nom de champs (ex: id). Il faudrait donc les préciser pour chaque table au lieu de mettre étoile ce qui serait énorme pour 22 tables qui contiennent chacune une dizaine de champs. De plus, il faudrait trier les résultats selon une colonne commune dans le select, ce qui implique de faire des unions et de préciser encore une fois toutes les tables communes. J'imagine que ce n'est pas la meilleure solution

    Auriez-vous une idée pour résoudre ce problème ?

    Merci de votre aide.

  2. #2
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 710
    Points : 4 794
    Points
    4 794
    Par défaut
    Si j'ai bien compris, tu veux parcourir plusieurs tables de structure différentes pour les trier sur un champ qu'elles auraient en commun (la date par exemple) et mettre le tout dans un fichier ?

    Si c'est le cas, java n'est pas la bonne solution car tu auras toujours un dépassement de mémoire.

    Dans ta base de données, il faut faire
    1) une table temporaire ayant comme structure les colonnes dont tu as besoin. (CREATE TABLE Temp ...)
    2) insérer dans cette table temporaire les données des différentes tables (INSERT INTO Temp ...)
    3) Faire une requête de tri (SELECT * FROM Temp ORDER BY ...) comme source d'un ResultSet
    4) Copier les données du ResultSet dans ton fichier

    Là ça marchera même avec pas beaucoup de mémoire car c'est le serveur de base de données qui fait le boulot (il est payé pour cela )
    Labor improbus omnia vincit un travail acharné vient à bout de tout - Ambroise Paré (1510-1590)

    Consulter sans modération la FAQ ainsi que les bons ouvrages : http://jmdoudoux.developpez.com/cours/developpons/java/

  3. #3
    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
    La table temporaire n'est pas indispensable, mais clairement, c'est un boulot pour la DB: écrit ta requête pour que tes données sortent dans l'ordre voulu et tu aura juste à les transcrire au fur et à mesure dans ton fichier.

    exemple de requête

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    select * from (
    select date, concat (id, ' ', name, ' ', firstname) from table1
    union
    select date, concat (key, ' ', company) from table2
    )
    order by date;

  4. #4
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 710
    Points : 4 794
    Points
    4 794
    Par défaut
    La table temporaire n'est pas indispensable
    En théorie tu as raison.
    Dans la pratique, il est plus sûr de passer par une table temporaire dont on va maîtriser la structure.
    Dans le cas décrit par Heavy Metal Hero, il y a 22 tables à additionner !!!
    L'optimiseur de la base va faire la gueule avec une requête union si les tables sont conséquentes.
    Labor improbus omnia vincit un travail acharné vient à bout de tout - Ambroise Paré (1510-1590)

    Consulter sans modération la FAQ ainsi que les bons ouvrages : http://jmdoudoux.developpez.com/cours/developpons/java/

  5. #5
    Membre averti
    Avatar de Heavy Metal Hero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juin 2007
    Messages : 152
    Points : 333
    Points
    333
    Billets dans le blog
    13
    Par défaut
    Merci de vos réponses, la solution de Népomucène était la bonne. J'ai créé une table temporaire contenant toutes les colonnes des autres tables en plus d'une contenant le nom de la table depuis laquelle l'entrée a été copiée. Les colonnes communes entre différentes tables (par exemple id, time, description) partagent la même colonne. J'ai récupéré les valeurs par blocs de 50 000 avec la requête de mon post. Ainsi triée, j'ai pu instancier les objets correspondants au valeurs vu que j'avais pour chacune d'entre elles le nom de la table.

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

Discussions similaires

  1. tracer le traitement d'une requête
    Par subzero82 dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 09/07/2008, 11h21
  2. cherche aide pour améliorer le traitement d'une requête
    Par nomade333 dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 22/04/2008, 14h15
  3. division par 0 dans une requête donne #Erreur
    Par bugprog dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 29/05/2007, 09h57
  4. Réponses: 3
    Dernier message: 28/02/2007, 18h46
  5. Réponses: 3
    Dernier message: 06/01/2006, 09h03

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