2009-09-23 7 views
4

Je reçois une grande quantité de données à partir d'une requête de base de données et j'en fais des objets. J'ai finalement une liste de ces objets (environ 1M d'entre eux) et je veux sérialiser cela sur disque pour une utilisation ultérieure. Le problème est qu'il ne rentre pas dans la mémoire et ne rentrera pas dans le futur, j'ai donc besoin d'un système pour sérialiser les 100k premiers, les 100k suivants etc .; et aussi pour lire les données en incréments de 100k.Sérialisation d'une très grande liste

Je pourrais faire un code évident qui vérifie si la liste devient trop grande et l'envoie ensuite au fichier 'list1', puis 'list2' etc. mais peut-être y a-t-il une meilleure façon de gérer cela?

+0

+1 pour une question intéressante. – KLE

Répondre

3

Vous pouvez parcourir la liste, créer un objet et l'envoyer immédiatement à un ObjectOutputStream qui les écrit dans le fichier.

+0

Mais l'OOS s'ajoute-t-il au fichier? Et y a-t-il une manière équivalente de lire les objets un par un à partir du fichier? – kresjer

+0

oui, il y a ObjectInputStream fait l'inverse –

+0

Bonne réponse. Pour info, j'ai fait quelque chose de similaire récemment, et j'ai remarqué de gros gains de performance en enveloppant mon FileOutputStream dans un BufferedOutputStream. À son tour, vous pouvez également lancer un GZIP OutputStream et économiser de l'espace disque: new ObjectOutputStream (nouveau GZIPOutputStream (nouveau BufferedOutputStream (nouveau FileOutputStream (myFile)))); –

2
  1. Lire les objets un par un à partir du DB

  2. Ne pas les mettre dans une liste, mais les écrire dans le fichier que vous les obtenez de la DB

Jamais garder plus d'un seul objet en RAM. Lorsque vous lisez l'objet, terminez la boucle de lecture lorsque readObject() renvoie null (= fin de fichier)

1

Je suppose que vous avez vérifié, il est vraiment nécessaire d'enregistrer les données sur le disque. Il ne pouvait pas rester dans la base de données, n'est-ce pas?


Pour traiter les données qui est trop grand, vous devez le rendre plus petit :-)

Une idée est de obtenir les données par morceaux:

  • début à la demande , donc vous ne construisez pas cette liste énorme (parce que cela deviendra un point de défaillance tôt ou tard)
  • sérialiser votre plus petite liste d'objets
  • puis boucle
1

Pensez à régler la taille d'extraction du pilote JDBC aussi, par exemple le pilote JDBC pour défaut de MySQL pour aller chercher l'ensemble de résultats.

lire ici pour plus d'informations: fetch size

0

Il semble que vous retreiving un grand ensemble de données db et les convertir en liste d'objets et de sérialisation en un seul coup. Ne faites pas cela .. enfin cela peut conduire à une panne de l'application.

Au lieu de cela vous avez à

  • réduire la quantité de données extraites de la base de données. (disons 1000 enregistrements au lieu de 1 M)
  • convertissez-les en objet métier
  • Et de les sérialiser.
  • Et effectuer la même procédure jusqu'à ce que le dernier enregistrement

cette façon, vous pouvez éviter le problème de performance. ObjectOutputStream fonctionnera mais il a plus de frais généraux.

0

Je pense que DataOutputStream/DataInputStream est un meilleur choix. Il suffit de lire/écrire un par un et laisser le flux s'inquiéter de la mise en mémoire tampon. Par exemple, vous pouvez faire quelque chose comme ça,

DataOutputStream os = new DataOutputStream(new FileOutputStream("myfile")); 
    for (...) 
     os.writeInt(num); 

Un Gotcha avec l'objet et le flux de données est write (int) écrit qu'un seul octet. Veuillez utiliser writeInt (int).

Questions connexes