queryset.iterator(chunk_size=None)(docs)

>>> users = User.objects.prefetch_related("favorite_set").iterator(chunk_size=3)
>>> for user in users:
...     print(f"user_id: {user.id}, favorites: {user.favorite_set.all()}")
... 

(0.000) SELECT "users_user"."id", "users_user"."username", "users_user"."password" FROM "users_user"; args=(); alias=default
(0.000) SELECT ("users_favorite_user"."user_id") AS "_prefetch_related_val_user_id", "users_favorite"."id", "users_favorite"."name" FROM "users_favorite" INNER JOIN "users_favorite_user" ON ("users_favorite"."id" = "users_favorite_user"."favorite_id") WHERE "users_favorite_user"."user_id" IN (1, 2, 3); args=(1, 2, 3); alias=default
user_id: 1, favorites: <QuerySet [<Favorite: Favorite object (1)>]>
user_id: 2, favorites: <QuerySet []>
user_id: 3, favorites: <QuerySet []>
(0.000) SELECT ("users_favorite_user"."user_id") AS "_prefetch_related_val_user_id", "users_favorite"."id", "users_favorite"."name" FROM "users_favorite" INNER JOIN "users_favorite_user" ON ("users_favorite"."id" = "users_favorite_user"."favorite_id") WHERE "users_favorite_user"."user_id" IN (4, 5, 6); args=(4, 5, 6); alias=default
user_id: 4, favorites: <QuerySet []>
user_id: 5, favorites: <QuerySet []>
user_id: 6, favorites: <QuerySet []>
...

# 한번 소비된 후에는 사용 불가
>>> next(users)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
StopIteration

with server-side cursor(docs)

Oracle(필수), PostgreSQL(선택)은 서버 커서를 기반으로 쿼리 결과를 메모리에 올리지 않고 데이터베이스에서 직접 스트리밍함

without server-side cursor(docs)

MySQL은 스트리밍을 지원하지 않기 때문에 결과 전체를 db 드라이버 수준에서 메모리에 저장하고 파이썬 객체로 변환해서 사용함

Paginator vs queryset.iterator() 비교

Efficient Iteration of Big Data in Django | NextLink Labs