Mysql
 sql >> Base de données >  >> RDS >> Mysql

Streaming de grands ensembles de résultats avec MySQL

Définir uniquement la taille d'extraction n'est pas la bonne approche. Le javadoc de Statement#setFetchSize() indique déjà ce qui suit :

Donne au pilote JDBC un indice quant au nombre de lignes qui doivent être extraites de la base de données

Le conducteur est en fait libre d'appliquer ou d'ignorer l'indice. Certains pilotes l'ignorent, certains pilotes l'appliquent directement, certains pilotes ont besoin de plus de paramètres. Le pilote MySQL JDBC appartient à la dernière catégorie. Si vous cochez le pilote MySQL JDBC documents , vous verrez les informations suivantes (faites défiler environ 2/3 vers le bas jusqu'à l'en-tête ResultSet ):

Pour activer cette fonctionnalité, vous devez créer une instance de Statement de la manière suivante :

stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);

Veuillez lire l'intégralité section du document, il décrit également les mises en garde de cette approche. Voici une citation pertinente :

Il y a quelques mises en garde avec cette approche. Vous devrez lire toutes les lignes du jeu de résultats (ou le fermer) avant de pouvoir émettre d'autres requêtes sur la connexion, sinon une exception sera levée.

(...)

Si l'instruction se trouve dans la portée d'une transaction, les verrous sont libérés lorsque la transaction se termine (ce qui implique que l'instruction doit d'abord se terminer). Comme avec la plupart des autres bases de données, les instructions ne sont pas terminées tant que tous les résultats en attente de l'instruction n'ont pas été lus ou que l'ensemble de résultats actif de l'instruction n'est pas fermé.

Si cela ne résout pas le problème OutOfMemoryError (pas Exception ), alors le problème est probablement que vous stockez toutes les données dans la mémoire de Java au lieu de les traiter immédiatement dès que les données arrivent. Cela nécessiterait plus de changements dans votre code, peut-être une réécriture complète. J'ai déjà répondu à une question similaire ici .