Używanie setFirstResult i setMaxResults to jedyna opcja, o której wiem.
Tradycyjnie przewijalny zestaw wyników przekazywałby wiersze do klienta tylko w razie potrzeby. Niestety, MySQL Connector/J faktycznie go fałszuje, wykonuje całe zapytanie i przesyła je do klienta, więc sterownik faktycznie ma cały zestaw wyników załadowany do pamięci RAM i przesyła go do ciebie (o czym świadczą problemy z brakiem pamięci) . Miałeś dobry pomysł, to tylko wady sterownika Java MySQL.
Nie znalazłem sposobu na obejście tego, więc poszedłem z ładowaniem dużych porcji przy użyciu zwykłych metod setFirst/max. Przykro mi, że jestem zwiastunem złych wiadomości.
Upewnij się tylko, że używasz sesji bezstanowej, aby nie było buforowania na poziomie sesji ani brudnego śledzenia itp.
EDYCJA:
Twoja UPDATE 2 jest najlepsza, jaką możesz uzyskać, chyba że wyrwiesz się z MySQL J/Connector. Chociaż nie ma powodu, dla którego nie możesz zwiększyć limitu zapytania. Zakładając, że masz wystarczająco dużo pamięci RAM do przechowywania indeksu, powinna to być dość tania operacja. Zmodyfikowałbym to nieznacznie i pobierał partię na raz i używał najwyższego identyfikatora tej partii, aby pobrać następną partię.
Uwaga:to zadziała tylko wtedy, gdy inne_warunki użyj równości (brak dozwolonych warunków zakresu) i ostatnia kolumna indeksu powinna mieć wartość id .
select *
from person
where id > <max_id_of_last_batch> and <other_conditions>
order by id asc
limit <batch_size>