In f4, are you not slowing things down by unpacking the list returned by Django only to create an identical list? I don't know how big your dataset is but I would expect `names = Song.objects.filter(artist=a).values_list("name", flat=True)` would be marginally quicker again.
I think if you do `names = Song.objects.filter(artist=a).values_list("name", flat=True)` then `names` would be a QuerySet instance, not a list. It's not till you start iterating on it that the actual SQL is created and transmitted to the database. But you're probably right that Django will internally consume a cursor fully first. However, if `iter(Song.objects.filter(artist=a).values_list("name", flat=True))` returns a list, and you loop over it, Python will not clone the memory into another place in the heap since lists a mutable. So the IO overhead will be near 0.
Comment
In f4, are you not slowing things down by unpacking the list returned by Django only to create an identical list? I don't know how big your dataset is but I would expect `names = Song.objects.filter(artist=a).values_list("name", flat=True)` would be marginally quicker again.
Replies
I think if you do `names = Song.objects.filter(artist=a).values_list("name", flat=True)` then `names` would be a QuerySet instance, not a list. It's not till you start iterating on it that the actual SQL is created and transmitted to the database. But you're probably right that Django will internally consume a cursor fully first. However, if `iter(Song.objects.filter(artist=a).values_list("name", flat=True))` returns a list, and you loop over it, Python will not clone the memory into another place in the heap since lists a mutable. So the IO overhead will be near 0.