On 9/18/15 3:22 PM, George Reilly wrote:
I find [SQLTap](http://sqltap.inconshreveable.com/) invaluable for profiling SQLAlchemy queries. Currently, I've reduced one operation in our system from nearly 12,000 queries to 800, and I'm not finished yet.

SQLTap listens for the before_execute and after_execute events. In after_execute, it captures the query time, the text of the query, and the parameters. These are aggregated into a profiling report.

For some queries, it fails to capture the actual parameter(s), instead reporting param_1 as None. The queries work, of course, and do have a non-None parameter. Typically these queries boil down to query(class).get(id).

Here's what the after_execute listener in SQLTap looks like (simplified):

    def _after_execute(self, conn, clause, multiparams, params, results):
        duration = time.time() - conn._sqltap_query_start_time
        try:
            text = clause.compile(dialect=conn.engine.dialect)
        except AttributeError:
            text = clause
        query_params = getattr(text, 'params', {})

I've set a breakpoint in _after_execute and examined the multiparams and params arguments. The results typically look like
multiparams ({'%(4480418320 param)s': 37},)
params {}
query_params {u'param_1': None}

I've put some sample code up at https://gist.github.com/georgevreilly/11f87d1d2f4664206df2
I'm using SQLAlchemy 0.9.9.

Is there a reliable way of capturing the actual query parameters?

the simplest way is to do it at the cursor using before_cursor_execute and after_cursor_execute which places the SQL string and the final parameters separately.

At the level of before_execute and after_execute, you'd need to recreate the arguments as they come from the given Core construct which means compiling it again which is not really something you want to be doing.

before_cursor_execute and after_cursor_execute provide all the information about the statement, compiled object, and everything else and is a more appropriate place to put performance-measuring callables, not to mention they isolate the time spent with the database itself much better. We've had an example of this at https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/Profiling for many years so I'm surprised SQLTap used the outer events, which are more intended for modifications to queries before they are invoked.



--
/George V. Reilly [email protected] <mailto:[email protected]> Twitter: @georgevreilly <https://twitter.com/georgevreilly>
_www.GeorgeVReilly.com <http://www.GeorgeVReilly.com>_
Please sponsor me for the End AIDS Walk: http://tinyurl.com/gvr-2015-aidswalk
--
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 [email protected] <mailto:[email protected]>. To post to this group, send email to [email protected] <mailto:[email protected]>.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

--
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to