Re: expected behavior of fetchmany()

Brian Jones <[email protected]> Wed, 3 Mar 2010 11:27:19 -0500
Newsgroups gmane.comp.python.db.psycopg.devel
Message-ID <[email protected]>
Thanks for the reply, Ben - please remember to cc/reply all to the list!

As for server side cursors, it's not clear that it solves the problem of
holding a single transaction open. I imagine that it performs all of its
work in a single transaction. I admit to being more familiar with pgsql than
psycopg2, so enlightenment is hereby solicited.

brian

On Wed, Mar 3, 2010 at 11:18 AM, Ben DeMott <[email protected]> wrote:

> Or you could use a Server-Side cursor, is this out of the question?
>
> On Wed, Mar 3, 2010 at 11:16 AM, Brian Jones <[email protected]> wrote:
>
>> Hi all,
>>
>> First, a hearty congrats on the new website, and the documentation. I've
>> used psycopg2 on and off for perhaps 4 years, and I discovered so much stuff
>> I never knew yesterday when I first discovered the docs. Can't thank you
>> enough. Keep it up.
>>
>> Second, the docs didn't answer this question :)
>> I have a query that returns millions of rows. I *was* wrapping the call in
>> a python generator that uses fetchmany(), but that's causing issues with big
>> result sets because fetchmany() doesn't create a new transaction for each of
>> its requests for the next chunk of data (more detail below) -- here's what
>> my generator looks like right now:
>>
>> def get_tons_o_data(self, params, limit=1000):
>>     cur = self.conn.cursor()
>>     cur.arraysize=limit
>>     try:
>>        cur.callproc('sch.get_metric_asston_o_data', params) # params is a
>> list
>>        while True:
>>           rs = cur.fetchmany(limit)
>>           if not rs:
>>              break
>>           for row in rs:
>>              yield row
>>      except Exception as out:
>>           <exception handling code here>
>>
>> This works really well for smaller result sets and provides a nice
>> interface for the code that uses it (for row in get_tons_o_data...). The
>> problem comes when I have millions of rows in the result set: the issue is
>> that fetchmany() holds a single transaction open until it has fetched the
>> entire result set instead of opening/closing a transaction for each chunk of
>> data it requests.
>>
>> I imagine this is probably expected behavior, but with so many rows being
>> returned, the transaction has the potential to stay open so long that it
>> keeps some database maintenance operations from running (some operations in
>> pgsql won't run if there's an open transaction, and won't kill the
>> transaction either).
>>
>> I guess I was looking more for something that would abstract out a sort of
>> 'limit/offset' loop for me. I'm updating the db function to take a limit and
>> offset, and then I'll have to create a loop to a) get data b) process data
>> c) update limit/offset d) rinse and repeat
>>
>> I just wanted to make sure I didn't miss some magical setting that would
>> cause fetchmany() to request each chunk of data in a separate transaction
>> before I started making alterations to my code.
>>
>> Thanks all.
>> brian
>>
>> --
>> Brian K. Jones
>> Python Magazine  http://www.pythonmagazine.com
>> My Blog          http://www.protocolostomy.com
>>
>> _______________________________________________
>> Psycopg mailing list
>> Psycopg-IAPFreCvJWPBWskQ1e/[email protected]
>> http://lists.initd.org/mailman/listinfo/psycopg
>>
>>
>


-- 
Brian K. Jones
Python Magazine  http://www.pythonmagazine.com
My Blog          http://www.protocolostomy.com

_______________________________________________
Psycopg mailing list
Psycopg-IAPFreCvJWPBWskQ1e/[email protected]
http://lists.initd.org/mailman/listinfo/psycopg