L'uso di setFirstResults e setMaxResults è l'unica opzione di cui sono a conoscenza.
Tradizionalmente un set di risultati scorrevole trasferirebbe le righe al client solo in base alle esigenze. Sfortunatamente MySQL Connector/J in realtà lo falsifica, esegue l'intera query e la trasporta al client, quindi il driver ha effettivamente l'intero set di risultati caricato nella RAM e te lo alimenterà (evidenziato dai tuoi problemi di memoria esaurita) . Hai avuto l'idea giusta, sono solo carenze nel driver java MySQL.
Non ho trovato alcun modo per aggirare questo problema, quindi sono andato a caricare blocchi di grandi dimensioni utilizzando i normali metodi setFirst/max. Mi dispiace essere portatore di cattive notizie.
Assicurati solo di utilizzare una sessione stateless in modo che non ci sia cache a livello di sessione o tracciamento sporco, ecc.
MODIFICA:
Il tuo UPDATE 2 è il meglio che otterrai a meno che non esca da MySQL J/Connector. Anche se non c'è motivo per cui non puoi aumentare il limite della query. A condizione che tu abbia abbastanza RAM per contenere l'indice, questa dovrebbe essere un'operazione alquanto economica. Lo modificherei leggermente, prenderò un batch alla volta e userei l'ID più alto di quel batch per prendere il batch successivo.
Nota:funzionerà solo se altre_condizioni utilizzare l'uguaglianza (nessuna condizione di intervallo consentita) e avere l'ultima colonna dell'indice come id .
select *
from person
where id > <max_id_of_last_batch> and <other_conditions>
order by id asc
limit <batch_size>