On Tuesday, 26 March 2013 14:54:08 UTC-7, Michael Bayer wrote:
>
>
> On Mar 26, 2013, at 5:24 PM, Laurence Rowe <lauren...@gmail.com<javascript:>> 
> wrote: 
>
> > I'd like to measure the number of database round trips that are 
> associated with a request to my web application so I can write tests to 
> catch potential performance regressions. I've been using 
> mock.Mock(wraps=connection.execute) to keep count and while I think this 
> works for selects, I don't have a good understanding of when executed 
> statements result in serialised network round trips or when they can be 
> 'pipelined', e.g. when inserting new rows. 
> > 
> > So to take a real example, posting to my web app results in the 
> insertion of a row in each of four tables. Afterwards, the 
> connection.execute mock's call_count is 4 and I see 4 INSERTs in my 
> sqlalchemy log: 
> > 
> > INFO:sqlalchemy.engine.base.Engine:INSERT INTO resources (rid) VALUES 
> (?) 
> > INFO:sqlalchemy.engine.base.Engine:('7745b647ff154ff39cedb897d4e2983c',) 
> > INFO:sqlalchemy.engine.base.Engine:INSERT INTO statements (rid, 
> predicate, object, tid) VALUES (?, ?, ?, ?) 
> > INFO:sqlalchemy.engine.base.Engine:('7745b647ff154ff39cedb897d4e2983c', 
> 'organism', '{"scientific_name": "Homo sapiens", "taxon_id": 9606, "_uuid": 
> "7745b647-ff15-4ff3-9ced-b897d4e2983c", "organism_name": "human"}', 
> 'edea69795dd14eb6bed73321cff54471') 
> > INFO:sqlalchemy.engine.base.Engine:INSERT INTO transactions (tid, data) 
> VALUES (?, ?) 
> > INFO:sqlalchemy.engine.base.Engine:('edea69795dd14eb6bed73321cff54471', 
> '{"tid": "edea6979-5dd1-4eb6-bed7-3321cff54471", "description": 
> "/organisms/", "user": " remoteuser:TEST"}') 
> > INFO:sqlalchemy.engine.base.Engine:INSERT INTO current_statements (rid, 
> predicate, sid) VALUES (?, ?, ?) 
> > INFO:sqlalchemy.engine.base.Engine:('7745b647ff154ff39cedb897d4e2983c', 
> 'organism', 1) 
> > 
> > Is there some way to tell which statements end up having data read from 
> the cursor? Here I have one dependent insert which required the 
> autoincremented primary key from a related row whereas the rest were fully 
> specified. 
>
> you can catch SQL traffic more directly using connection events, there are 
> two varieties, one catches the high level SQL expression construct, and the 
> other catches the activity at the level of cursor.execute() or 
> cursor.executemany() (DBAPI cursor).    Intercepting execute/executemany is 
> the most accurate way to see all DBAPI interaction fully and exactly as 
> it's being passed: 
>
>
> http://docs.sqlalchemy.org/en/rel_0_8/core/events.html#sqlalchemy.events.ConnectionEvents.before_cursor_execute
>  
>
> http://docs.sqlalchemy.org/en/rel_0_8/core/events.html#sqlalchemy.events.ConnectionEvents.after_cursor_execute
>  
>
> next aspect, if you consider SELECT statements as those which read data 
> from the cursor, you can tell if a cursor has results pending on it by 
> checking if cursor.description is not None.  You can check for this inside 
> of the after_cursor_execute event.   
>
> if you're trying to look at INSERT statements and distinguish between 
> those which use an "implicit" autoincrementing primary key and those which 
> have it specified, depending on specifics this might be more 
> straightforward at the SQL expression level, if you are using 
> table.insert() constructs (or via the ORM which also does).    A generic 
> way would be to look at the Table that's the subject of the insert, then 
> looking at the parameters to see if parameters referring to a full primary 
> key are present.  These values are all present on the context passed to the 
> execute events.    Another way that might work more expediently, but is a 
> little more of an "inside" method, is to take a look at 
> context.inserted_primary_key inside of the after_cursor_execute event; if 
> it contains a full primary key without the value None present, that means 
> the dialect knew ahead of time the full primary key value (this will only 
> be filled in for a single statement execute, not an executemany). 
>
> I can work up an example using any combination of these techniques, if you 
> can let me know which might seem workable.


Thanks, moving to a connection event seems like a cleaner way to measure 
this than the mock.

When using the ORM, does SA always fetch any db generated primary key? 
(Either through a sequence preexecute or by subsequently reading from the 
cursor metadata depending on the dialect.) If not, then ideally I'd want 
only those that were fetched for use in a subsequent insert. If so, then I 
should probably tweak my structure - I'm only really using a non-UUID 
primary key because it was the easiest way to get an autoincrementing 
column in SQLite... Deployment will be on Postgres.

I had another idea to look for UOWTransaction.cycles evaluating True, but I 
think that might be telling me something different.

Laurence

-- 
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