Ok, so yield_per() is useless when subqueryload() is used.

Thank you,

Ladislav Lenart


On 5.6.2013 16:27, Michael Bayer wrote:
> the Query emitted by subqueryload does not use yield_per.  so if your total 
> result set is 1000 rows, and the total rows represented by all the 
> collections is 10000,  the first time that query is emitted, 10000 rows will 
> be fully loaded and processed into memory at once.  This would occur 
> typically somewhere in the first few rows of your 50 -row yield_per batch.   
> So the intent of yield_per, which is to conserve memory and upfront loading 
> overhead, would be defeated entirely by this.
> 
> The subqueryload is emitting once if I recall correctly because I probably at 
> some point have the query result being memoized in the query context to 
> prevent it from being emitted many times in a yield_per scenario.
> 
> 
> On Jun 5, 2013, at 10:20 AM, Ladislav Lenart <lenart...@volny.cz> wrote:
> 
>> Hello.
>>
>> One more note. I've just tried the below experiment with joinedload() 
>> instead of
>> subqueryload() and that does NOT work just as you expected. One contact is
>> returned several times and the first occurrences have incomplete phones.
>>
>> However my experiments with subqueryload() suggest that it works just fine 
>> with
>> yield_per(). Can you elaborate on that one please?
>>
>>
>> Thank you,
>>
>> Ladislav Lenart
>>
>>
>> On 5.6.2013 14:03, Ladislav Lenart wrote:
>>> Hello.
>>>
>>> I've tried an experiment to verify that yield_per() with subqueryload() 
>>> behaves
>>> as badly as you described, but according to my practical observation, it 
>>> issues
>>> ONE subqueryload() and everything behaves as I would expect. It emits two
>>> SELECTs, one to fetch the objects and the second one to fetch the related 
>>> data
>>> and that's about it, see below. So back to square one, what is wrong with 
>>> it?
>>>
>>>
>>> Base = declarative_base()
>>>
>>> class Contact(Base):
>>>    # Just a sketch, I hope you get the picture.
>>>    id,
>>>    name,
>>>    phones = relationship(Phone) # many
>>>
>>> class Phone(Base):
>>>    # Just a sketch, I hope you get the picture.
>>>    id,
>>>    number,
>>>    contact = relationship(Contact) # one
>>>
>>> # Setup engine with echo set to True.
>>>
>>> phones = ['123456789', '987654321', '555777999']
>>> for i in range(1, 11):
>>>    c = Contact(name=u' '.join([u'Contact', unicode(i)]))
>>>    session.add(c)
>>>    session.add_all(Phone(contact=c, number=e) for e in phones)
>>> session.flush()
>>> session.expunge_all()
>>>
>>> q = session.query(Contact).options(subqueryload(Contact.phones))
>>> for each in q.yield_per(2):
>>>    print each.last_name
>>>    for e in each.phones:
>>>        print e
>>>
>>> The output is like this:
>>> SA info about all the inserts after session.flush().
>>> SA info about select for contacts.
>>> SA info about select for their phones.
>>> Contact 10
>>> 123456789
>>> 987654321
>>> 555777999
>>> Contact 9
>>> 123456789
>>> 987654321
>>> 555777999
>>> Contact 8
>>> 123456789
>>> 987654321
>>> 555777999
>>> Contact 7
>>> 123456789
>>> 987654321
>>> 555777999
>>> Contact 6
>>> 123456789
>>> 987654321
>>> 555777999
>>> Contact 5
>>> 123456789
>>> 987654321
>>> 555777999
>>> Contact 4
>>> 123456789
>>> 987654321
>>> 555777999
>>> Contact 3
>>> 123456789
>>> 987654321
>>> 555777999
>>> Contact 2
>>> 123456789
>>> 987654321
>>> 555777999
>>> Contact 1
>>> 123456789
>>> 987654321
>>> 555777999
>>>
>>>
>>> Thank you,
>>>
>>> Ladislav Lenart
>>>
>>>
>>> On 5.6.2013 11:26, Ladislav Lenart wrote:
>>>> Hello.
>>>>
>>>> I have one more question about my approach to WindowedRangeQuery:
>>>>
>>>>> * Suppose a complex query q with join(...), filter(...) and options(...).
>>>>> * I need to create q2 from q such that:
>>>>> * It has no options.
>>>>>   * Can I reset the options with q = q.options(None)?
>>>>> * It has select with the over by magic taken from WindowedRangeQuery 
>>>>> recipe.
>>>>>   * I know I can use with_entities() for this.
>>>>> * I will use q2 to obtain the window ranges.
>>>>> * I will iterate over the window ranges and apply each to the original q 
>>>>> and
>>>>> execute it in a loop.
>>>>
>>>> Suppose I have a complex query (without options() / order_by()) to obtain 
>>>> the
>>>> objects I want. I use this query to calculate window intervals. I don't 
>>>> have to
>>>> use it again to fetch the objects, because I already have their id 
>>>> intervals. Am
>>>> I right?
>>>>
>>>>
>>>> Thank you,
>>>>
>>>> Ladislav Lenart
>>>>
>>>>
>>>> On 4.6.2013 19:15, Ladislav Lenart wrote:
>>>>> On 4.6.2013 18:49, Michael Bayer wrote:
>>>>>>
>>>>>> On Jun 4, 2013, at 12:28 PM, Ladislav Lenart <lenart...@volny.cz> wrote:
>>>>>>
>>>>>>>
>>>>>>>> Absolutely, you should do whatever you have to in order to get the 
>>>>>>>> range
>>>>>>>> you want, in fact the recipe even says this...
>>>>>>>
>>>>>>> Ok. What I want to do is basically the following:
>>>>>>> * Suppose a complex query q with join(...), filter(...) and 
>>>>>>> options(...).
>>>>>>> * I need to create q2 from q such that:
>>>>>>> * It has no options.
>>>>>>>   * Can I reset the options with q = q.options(None)?
>>>>>>> * It has select with the over by magic taken from WindowedRangeQuery 
>>>>>>> recipe.
>>>>>>>   * I know I can use with_entities() for this.
>>>>>>> * I will use q2 to obtain the window ranges.
>>>>>>> * I will iterate over the window ranges and apply each to the original 
>>>>>>> q and
>>>>>>> execute it in a loop.
>>>>>>>
>>>>>>> Can this strategy work?
>>>>>>
>>>>>> there's not a publicly supported feature to "reset" the options right 
>>>>>> now so you'd probably need to apply them after you get your window 
>>>>>> ranging query.      You can probably remove the effect of eager loaders 
>>>>>> if you were to just assign a blank _attributes dictionary to the new 
>>>>>> query though (just no long term guarantees).
>>>>>>
>>>>>> other than that, I use the windowing concept extensively and it works 
>>>>>> very well.
>>>>>
>>>>> Ok, I will try it.
>>>>>
>>>>> Thank you very much for your invaluable insights,
>>>>>
>>>>> Ladislav Lenart
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "sqlalchemy" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to sqlalchemy+unsubscr...@googlegroups.com.
>> To post to this group, send email to sqlalchemy@googlegroups.com.
>> Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
>> For more options, visit https://groups.google.com/groups/opt_out.

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to