Nate C estava perto, mas não exatamente.
Dos documentos:
Você pode avaliar um QuerySet das seguintes maneiras:
Iteração. Um QuerySet é iterável e executa sua consulta de banco de dados na primeira vez que você iterar sobre ele. Por exemplo, isso imprimirá o título de todas as entradas no banco de dados:
for e in Entry.objects.all(): print e.headline
Assim, seus dez milhões de linhas são recuperadas, todas de uma vez, quando você entra nesse loop pela primeira vez e obtém a forma iterativa do conjunto de consultas. A espera que você experimenta é o Django carregando as linhas do banco de dados e criando objetos para cada uma, antes de retornar algo que você possa realmente iterar. Então você tem tudo na memória, e os resultados vêm à tona.
Da minha leitura dos documentos,
iterator()
não faz nada além de ignorar os mecanismos de cache internos do QuerySet. Acho que pode fazer sentido fazer uma coisa por uma, mas isso exigiria dez milhões de acessos individuais em seu banco de dados. Talvez não tão desejável. Iterar em grandes conjuntos de dados com eficiência é algo que ainda não acertamos, mas existem alguns snippets que podem ser úteis para seus propósitos:
- Iterador Django QuerySet com memória eficiente
- conjuntos de consultas em lote
- QuerySet Foreach