J'ai simplement besoin de lire chaque ligne d'une table de ma base de données MySQL à l'aide d'Hibernate et d'écrire un fichier sur cette base. Mais il y a 90 millions de lignes et elles sont plutôt grosses. Il m'a donc semblé que la méthode suivante serait appropriée :
ScrollableResults results = session.createQuery("SELECT person FROM Person person")
.setReadOnly(true).setCacheable(false).scroll(ScrollMode.FORWARD_ONLY);
while (results.next())
storeInFile(results.get()[0]);
Le problème est que le programme ci-dessus va essayer de charger les 90 millions de lignes dans la RAM avant de passer à la boucle while... et cela va tuer ma mémoire avec OutOfMemoryError : Java heap space exceptions :(.
Je suppose donc que ScrollableResults n'est pas ce que je recherchais ? Quelle est la bonne façon de gérer cela ? Cela ne me dérange pas si cette boucle while prend des jours (enfin, j'aimerais bien que ce ne soit pas le cas).
Je suppose que la seule autre façon de gérer cela est d'utiliser setFirstResult et setMaxResults pour itérer dans les résultats et utiliser les résultats Hibernate normaux au lieu des ScrollableResults. Mais cela semble inefficace et prendra un temps fou lorsque j'appellerai setFirstResult à la 89 millionième ligne...
MISE À JOUR : setFirstResult/setMaxResults ne fonctionne pas, il s'avère que cela prend un temps anormalement long pour arriver aux offsets comme je le craignais. Il doit y avoir une solution ! N'est-ce pas une procédure assez standard ? Je suis prêt à renoncer à Hibernate et à utiliser JDBC ou ce qu'il faut.
MISE À JOUR 2 : la solution que j'ai trouvée, qui fonctionne bien, mais pas super, est essentiellement de la forme suivante :
select * from person where id > <offset> and <other_conditions> limit 1
Comme j'ai d'autres conditions, même toutes dans un index, ce n'est toujours pas aussi rapide que je le voudrais... donc toujours ouvert à d'autres suggestions...