Att använda setFirstResult och setMaxResults är ditt enda alternativ som jag känner till.
Traditionellt skulle en rullningsbar resultatuppsättning endast överföra rader till klienten efter behov. Tyvärr förfalskar MySQL Connector/J den, den kör hela frågan och transporterar den till klienten, så att drivrutinen faktiskt har hela resultatuppsättningen laddad i RAM-minnet och kommer att droppmata den till dig (bevisas av dina problem med minnet) . Du hade rätt idé, det är bara brister i MySQL java-drivrutinen.
Jag hittade inget sätt att komma runt detta, så jag började ladda stora bitar med de vanliga setFirst/max-metoderna. Ledsen att jag förmedlar dåliga nyheter.
Se bara till att använda en tillståndslös session så att det inte finns någon cache på sessionsnivå eller smutsig spårning etc.
EDIT:
Din UPPDATERING 2 är den bästa du kommer att få om du inte bryter dig ur MySQL J/Connector. Även om det inte finns någon anledning till att du inte kan öka gränsen för frågan. Förutsatt att du har tillräckligt med RAM-minne för att hålla indexet borde detta vara en ganska billig operation. Jag skulle ändra det något och ta en batch i taget och använda det högsta ID:t för den batchen för att ta nästa batch.
Obs:detta fungerar bara om other_conditions använd likhet (inga intervallvillkor tillåtna) och ha den sista kolumnen i indexet som id .
select *
from person
where id > <max_id_of_last_batch> and <other_conditions>
order by id asc
limit <batch_size>